Files
IPB/applications/core/modules/front/system/vnc.php
T
2025-12-19 04:57:54 -08:00

694 lines
24 KiB
PHP

<?php
/**
* @brief New Content
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @since 18 Apr 2014
* @version SVN_VERSION_NUMBER
*/
namespace IPS\core\modules\front\system;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* New Content
*/
class _vnc extends \IPS\Dispatcher\Controller
{
/**
* New Content
*
* @return void
*/
public function manage()
{
/* Flood control */
\IPS\Request::floodCheck();
if( isset( \IPS\Request::i()->nodes ) )
{
\IPS\Request::i()->nodes = urldecode( \IPS\Request::i()->nodes );
}
/* Logged in only */
if ( !\IPS\Member::loggedIn()->member_id )
{
\IPS\Output::i()->error( 'no_module_permission_guest', '2C232/1', 403, '' );
}
elseif( !\IPS\Request::i()->updateFilters )
{
$preferences = json_decode( \IPS\Member::loggedIn()->vnc_preferences, TRUE );
if( isset( $preferences['onlyFollowed'] ) AND !isset( \IPS\Request::i()->onlyFollowed ) )
{
\IPS\Request::i()->onlyFollowed = $preferences['onlyFollowed'];
}
if( isset( $preferences['onlyParticipated'] ) AND !isset( \IPS\Request::i()->onlyParticipated ) )
{
\IPS\Request::i()->onlyParticipated = $preferences['onlyParticipated'];
}
if( isset( $preferences['onlyStarted'] ) AND !isset( \IPS\Request::i()->onlyStarted ) )
{
\IPS\Request::i()->onlyStarted = $preferences['onlyStarted'];
}
if( isset( $preferences['onlyUnread'] ) AND !isset( \IPS\Request::i()->onlyUnread ) )
{
\IPS\Request::i()->onlyUnread = $preferences['onlyUnread'];
}
if( isset( $preferences['searchType'] ) AND !isset( \IPS\Request::i()->type ) )
{
\IPS\Request::i()->type = $preferences['searchType'];
}
if( isset( $preferences['vncTimePeriod'] ) AND !isset( \IPS\Request::i()->vncTimePeriod ) )
{
\IPS\Request::i()->vncTimePeriod = $preferences['vncTimePeriod'];
}
if( isset( $preferences['container'] ) AND !isset( \IPS\Request::i()->nodes ) )
{
\IPS\Request::i()->nodes = $preferences['container'];
}
}
/* Though this isn't part of search, disabling the search module will disable it */
if ( !\IPS\Member::loggedIn()->canAccessModule( \IPS\Application\Module::get( 'core', 'search' ) ) )
{
\IPS\Output::i()->error( 'no_module_permission', '2C232/2', 403, '' );
}
/* Init */
$baseUrl = \IPS\Http\Url::internal( 'app=core&module=system&controller=vnc&updateFilters=1', 'front', 'vnc' );
$nodeSelect = NULL;
$nodeTitle = NULL;
/* Get types */
$types = array();
foreach ( \IPS\Content::routedClasses( TRUE, FALSE, TRUE ) as $class )
{
if( is_subclass_of( $class, 'IPS\Content\ReadMarkers' ) )
{
$key = mb_strtolower( str_replace( '\\', '_', mb_substr( $class, 4 ) ) );
$types[ $key ] = $class;
}
}
/* If a user last filtered by "downloads_file" and then the download manager app was disabled we need to clear this otherwise you get a fatal error */
if ( \IPS\Request::i()->type AND \IPS\Request::i()->type !== 'all' AND !isset( $types[ \IPS\Request::i()->type ] ) )
{
\IPS\Request::i()->type = '';
}
/* Force a type if only one available */
if( count( $types ) == 1 )
{
$keys = array_keys( $types );
\IPS\Request::i()->type = array_shift( $keys );
}
/* Set filters */
$where = array();
$start = NULL;
$end = NULL;
$onlyUnread = FALSE;
if ( isset( \IPS\Request::i()->onlyUnread ) and \IPS\Request::i()->onlyUnread )
{
$baseUrl = $baseUrl->setQueryString( 'onlyUnread', 1 );
$onlyUnread = TRUE;
}
$onlyFollowed = FALSE;
if ( isset( \IPS\Request::i()->onlyFollowed ) and \IPS\Request::i()->onlyFollowed )
{
$baseUrl = $baseUrl->setQueryString( 'onlyFollowed', 1 );
$onlyFollowed = TRUE;
$where[] = array( 'follow_id IS NOT NULL AND follow_member_id =?', \IPS\Member::loggedIn()->member_id );
}
$onlyParticipated = FALSE;
if ( isset( \IPS\Request::i()->onlyParticipated ) and \IPS\Request::i()->onlyParticipated )
{
$baseUrl = $baseUrl->setQueryString( 'onlyParticipated', 1 );
$onlyParticipated = TRUE;
}
$onlyStarted = FALSE;
if ( isset( \IPS\Request::i()->onlyStarted ) and \IPS\Request::i()->onlyStarted )
{
$baseUrl = $baseUrl->setQueryString( 'onlyStarted', 1 );
$onlyStarted = TRUE;
}
/* Get cutoff */
$interval = NULL;
$vncTimePeriod = NULL;
if ( isset( \IPS\Request::i()->vncTimePeriod ) )
{
$vncTimePeriod = \IPS\Request::i()->vncTimePeriod;
$baseUrl = $baseUrl->setQueryString( 'vncTimePeriod', $vncTimePeriod );
if ( isset( \IPS\Request::i()->vncTime ) )
{
$start = \IPS\DateTime::ts( \IPS\Request::i()->vncTime, TRUE );
}
switch ( $vncTimePeriod )
{
case 'all':
$cutoff = NULL;
break;
case 'day':
$interval = new \DateInterval( 'P1D' );
if ( !$start )
{
$start = \IPS\DateTime::ts( \IPS\DateTime::create()->getTimestamp(), TRUE )->sub( $interval );
}
else
{
$end = \IPS\DateTime::ts( $start->getTimestamp(), TRUE )->add( $interval );
}
break;
case 'week':
$interval = new \DateInterval( 'P1W' );
if ( !$start )
{
$start = \IPS\DateTime::ts( \IPS\DateTime::create()->getTimestamp(), TRUE )->sub( $interval );
}
else
{
$end = \IPS\DateTime::ts( $start->getTimestamp(), TRUE )->add( $interval );
}
break;
case 'month':
$interval = new \DateInterval( 'P1M' );
if ( !$start )
{
$start = \IPS\DateTime::create()->sub( $interval );
}
else
{
$end = \IPS\DateTime::ts( $start->getTimestamp(), TRUE )->add( $interval );
}
break;
default:
$start = \IPS\DateTime::ts( \IPS\Member::loggedIn()->last_visit, TRUE );
break;
}
}
else
{
$start = \IPS\DateTime::ts( \IPS\Member::loggedIn()->last_visit, TRUE );
}
if( \IPS\Member::loggedIn()->member_id and isset( \IPS\Request::i()->updateFilters ) )
{
$vncPreferences = json_encode( array(
'onlyFollowed' => $onlyFollowed,
'onlyParticipated' => $onlyParticipated,
'onlyStarted' => $onlyStarted,
'onlyUnread' => $onlyUnread,
'searchType' => \IPS\Request::i()->type ?: NULL,
'vncTimePeriod' => $vncTimePeriod,
'container' => \IPS\Request::i()->nodes ?: NULL,
) );
if ( $vncPreferences != \IPS\Member::loggedIn()->vnc_preferences )
{
\IPS\Member::loggedIn()->vnc_preferences = $vncPreferences;
\IPS\Member::loggedIn()->save();
}
}
/* Get results - if we're just searching one type, it's a bit simpler */
if ( \IPS\Request::i()->type AND \IPS\Request::i()->type !== 'all' )
{
/* Init */
$baseUrl = $baseUrl->setQueryString( 'type', \IPS\Request::i()->type );
$class = $types[ \IPS\Request::i()->type ];
if ( $onlyUnread )
{
$unreadWhere = $this->_getUnreadWhere( $class );
if ( count( $unreadWhere ) )
{
foreach( $unreadWhere as $id => $item )
{
$where[] = $item;
}
}
}
/* Where */
if ( $onlyParticipated or $onlyStarted )
{
if( isset( $class::$databaseColumnMap['author'] ) )
{
$participatedWhere[] = $class::$databaseTable . '.' . $class::$databasePrefix . $class::$databaseColumnMap['author'] . '=' . \IPS\Member::loggedIn()->member_id;
}
if ( !$onlyStarted )
{
if( isset( $class::$commentClass ) )
{
$commentClass = $class::$commentClass;
$participatedWhere[] = '(' . str_replace( "`", '', (string) \IPS\Db::i()->select( 'COUNT(*)', $commentClass::$databaseTable, $commentClass::$databaseTable . '.' . $commentClass::$databasePrefix . $commentClass::$databaseColumnMap['author'] . '=' . \IPS\Member::loggedIn()->member_id . ' AND ' .
$commentClass::$databaseTable . '.' . $commentClass::$databasePrefix . $commentClass::$databaseColumnMap['item'] . '=' . $class::$databaseTable . '.' . $class::$databasePrefix . $class::$databaseColumnId ) ) . ') > 0';
}
if( isset( $class::$reviewClass ) )
{
$reviewClass = $class::$reviewClass;
$participatedWhere[] = '(' . str_replace( "`", '', (string) \IPS\Db::i()->select( 'COUNT(*)', $reviewClass::$databaseTable, $reviewClass::$databaseTable . '.' . $reviewClass::$databasePrefix . $reviewClass::$databaseColumnMap['author'] . '=' . \IPS\Member::loggedIn()->member_id . ' AND ' .
$reviewClass::$databaseTable . '.' . $reviewClass::$databasePrefix . $reviewClass::$databaseColumnMap['item'] . '=' . $class::$databaseTable . '.' . $class::$databasePrefix . $class::$databaseColumnId ) ) . ') > 0';
}
}
$where[] = array( '( ' . implode( ' OR ', $participatedWhere ) . ' )' );
}
/* Node Filter */
if ( $class::$containerNodeClass )
{
$node = NULL;
$nodeClass = $class::$containerNodeClass;
$nodeTitle = \IPS\Member::loggedIn()->language()->addToStack( $nodeClass::$nodeTitle );
if ( isset( \IPS\Request::i()->nodes ) and \IPS\Request::i()->nodes )
{
try
{
$baseUrl = $baseUrl->setQueryString( 'nodes', \IPS\Request::i()->nodes );
$where[] = array( \IPS\Db::i()->in( $class::$databaseTable . '.' . $class::$databasePrefix . $class::$databaseColumnMap['container'], is_array( \IPS\Request::i()->nodes ) ? \IPS\Request::i()->nodes : explode( ',', \IPS\Request::i()->nodes ) ) );
}
catch ( \OutOfRangeException $e ) { }
}
$nodeSelect = new \IPS\Helpers\Form\Node( 'nodes', ( is_array( \IPS\Request::i()->nodes ) ) ? \IPS\Request::i()->nodes : explode( ',', \IPS\Request::i()->nodes ), FALSE, array( 'class' => $class::$containerNodeClass, 'permissionCheck' => 'view', 'url' => $baseUrl, 'multiple' => TRUE ) );
}
/* Cutoff */
$dateColumnExpression = $this->_getDateExpression( $class );
if ( $start )
{
$where[] = array( $dateColumnExpression . '>?', $start->getTimestamp() );
}
if ( $end )
{
$where[] = array( $dateColumnExpression . '<?', $end->getTimestamp() );
}
if ( isset( $class::$databaseColumnMap['state'] ) )
{
$where[] = array( $class::$databaseTable . '.' . $class::$databasePrefix . $class::$databaseColumnMap['state'] . "!=?", 'link' );
}
/* Create table */
$table = new \IPS\Helpers\Table\Content( $class, $baseUrl, $where, NULL, NULL, 'read', FALSE );
$table->classes[] = 'ipsDataList_zebra';
$table->sortOptions = array();
$table->noModerate = TRUE;
/* Joins */
if ( $onlyFollowed )
{
$followArea = mb_strtolower( mb_substr( $class, mb_strrpos( $class, '\\' ) + 1 ) );
$table->joins[] = array( 'from' => 'core_follow', 'where' => array( "follow_app=? AND follow_area=? AND follow_member_id=? AND follow_rel_id={$class::$databasePrefix}{$class::$databaseColumnId}", $class::$application, $followArea, \IPS\Member::loggedIn()->member_id ) );
}
}
/* If we're searching them all, we need to go all union */
else
{
/* Build the selects */
$selects = array();
foreach ( $types as $key => $class )
{
$dateColumnExpression = $this->_getDateExpression( $class );
/* Normalize the columns */
$contentWhere = array();
$columns = array(
$class::$databaseTable . "." . $class::$databasePrefix.$class::$databaseColumnId => 'id',
$dateColumnExpression => 'date',
$class::$databaseTable . "." . $class::$databasePrefix.$class::$databaseColumnMap['author'] => 'author'
);
if ( in_array( 'IPS\Content\Hideable', class_implements( $class ) ) and !\IPS\Member::loggedIn()->modPermission( "can_view_hidden_content" ) )
{
if ( $class::$databaseColumnMap['approved'] )
{
$columns[ $class::$databaseTable . "." . $class::$databasePrefix.$class::$databaseColumnMap['approved'] . '-1' ] = 'hidden';
$contentWhere[] = array( $class::$databaseTable . "." . $class::$databasePrefix.$class::$databaseColumnMap['approved'] . '-1=0' );
}
else
{
$columns[ $class::$databaseTable . "." . $class::$databasePrefix.$class::$databaseColumnMap['hidden'] ] = 'hidden';
$contentWhere[] = array( $class::$databaseTable . "." . $class::$databasePrefix.$class::$databaseColumnMap['hidden'] . '=0' );
}
}
$select = array( "'".str_replace( '\\', '\\\\' , $class ) ."' AS class" );
foreach ( $columns as $local => $normalized )
{
$select[] = "{$local} AS {$normalized}";
}
if ( $onlyFollowed )
{
$select[] = "'".$class::$application."' AS _app";
$followArea = mb_strtolower( mb_substr( $class, mb_strrpos( $class, '\\' ) + 1 ) );
$select[] = "'{$followArea}' AS _follow_area";
}
$select = implode( ', ', $select );
/* Permissions */
if ( in_array( 'IPS\Content\Permissions', class_implements( $class ) ) )
{
$containerClass = $class::$containerNodeClass;
$categories = array();
foreach( \IPS\Db::i()->select( 'perm_type_id', 'core_permission_index', array( "core_permission_index.app='" . $containerClass::$permApp . "' AND core_permission_index.perm_type='" . $containerClass::$permType . "' AND (" . \IPS\Db::i()->findInSet( 'perm_' . $containerClass::$permissionMap['read'], \IPS\Member::loggedIn()->groups ) . ' OR ' . 'perm_' . $containerClass::$permissionMap['read'] . "='*' )" ) ) as $result )
{
$categories[] = $result;
}
if( count( $categories ) )
{
$contentWhere[] = array( $class::$databaseTable . '.' . $class::$databasePrefix . $class::$databaseColumnMap['container'] . ' IN(' . implode( ',', $categories ) . ')' );
}
else
{
$contentWhere[] = array( $class::$databaseTable . "." . $class::$databasePrefix . $class::$databaseColumnMap['container'] . '=0' );
}
}
/* Future */
if ( in_array( 'IPS\Content\FuturePublishing', class_implements( $class ) ) and !$class::canViewFutureItems() )
{
$authorCol = $class::$databaseTable . '.' . $class::$databasePrefix . $class::$databaseColumnMap['author'];
$col = $class::$databaseTable . '.' . $class::$databasePrefix . $class::$databaseColumnMap['is_future_entry'];
$contentWhere[] = array( "( {$col}=0 OR ( {$col}=1 AND {$authorCol}=" . \IPS\Member::loggedIn()->member_id . " ) )" );
}
/* Add app-sepcific wheres */
$joinContainer = FALSE;
$joins = array();
$vncWhere = $class::vncWhere( $joinContainer, $joins );
if ( is_array( $vncWhere ) )
{
foreach( $vncWhere as $key => $value )
{
if ( $key ==='item' )
{
$contentWhere = array_merge( $contentWhere, $value );
}
else if ( $key === 'container' )
{
$contentWhere = array_merge( $contentWhere, $value );
}
else
{
$contentWhere[] = $value;
}
}
}
/* Only unread */
if ( $onlyUnread )
{
$unreadWhere = $this->_getUnreadWhere( $class );
if ( count( $unreadWhere ) )
{
foreach( $unreadWhere as $id => $item )
{
$contentWhere[] = $item;
}
}
}
/* Participated Only */
if ( $onlyParticipated or $onlyStarted )
{
$participatedWhere = array();
if( isset( $class::$databaseColumnMap['author'] ) )
{
$participatedWhere[] = $class::$databaseTable . '.' . $class::$databasePrefix . $class::$databaseColumnMap['author'] . '=' . \IPS\Member::loggedIn()->member_id;
}
if ( !$onlyStarted )
{
if( isset( $class::$commentClass ) )
{
$commentClass = $class::$commentClass;
$participatedWhere[] = '(' . str_replace( "`", '', (string) \IPS\Db::i()->select( 'COUNT(*)', $commentClass::$databaseTable, $commentClass::$databaseTable . '.' . $commentClass::$databasePrefix . $commentClass::$databaseColumnMap['author'] . '=' . \IPS\Member::loggedIn()->member_id . ' AND ' .
$commentClass::$databaseTable . '.' . $commentClass::$databasePrefix . $commentClass::$databaseColumnMap['item'] . '=' . $class::$databaseTable . '.' . $class::$databasePrefix . $class::$databaseColumnId ) ) . ') > 0';
}
if( isset( $class::$reviewClass ) )
{
$reviewClass = $class::$reviewClass;
$participatedWhere[] = '(' . str_replace( "`", '', (string) \IPS\Db::i()->select( 'COUNT(*)', $reviewClass::$databaseTable, $reviewClass::$databaseTable . '.' . $reviewClass::$databasePrefix . $reviewClass::$databaseColumnMap['author'] . '=' . \IPS\Member::loggedIn()->member_id . ' AND ' .
$reviewClass::$databaseTable . '.' . $reviewClass::$databasePrefix . $reviewClass::$databaseColumnMap['item'] . '=' . $class::$databaseTable . '.' . $class::$databasePrefix . $class::$databaseColumnId ) ) . ') > 0';
}
}
$contentWhere[] = '( ' . implode( ' OR ', $participatedWhere ) . ' )';
}
if ( isset( $class::$databaseColumnMap['state'] ) )
{
$contentWhere[] = array( $class::$databaseTable . '.' . $class::$databasePrefix . $class::$databaseColumnMap['state'] . "!='link'" );
}
/* Add to the list */
$select = \IPS\Db::i()->select( $select, $class::$databaseTable, $contentWhere );
if ( $joinContainer )
{
$containerClass = $class::$containerNodeClass;
$select->join( $containerClass::$databaseTable, $class::$databaseTable . "." . $class::$databasePrefix . $class::$databaseColumnMap['container'] . '=' . $containerClass::$databaseTable . "." . $containerClass::$databasePrefix . $containerClass::$databaseColumnId );
}
if ( count( $joins ) )
{
foreach ( $joins as $join )
{
$select->join( $join['from'], $join['where'] );
}
}
$selects[] = $select;
}
/* Cutoff */
if ( $start )
{
$where[] = array( 'date>?', $start->getTimestamp() );
}
if ( $end )
{
$where[] = array( 'date<?', $end->getTimestamp() );
}
$page = isset( \IPS\Request::i()->page ) ? intval( \IPS\Request::i()->page ) : 1;
if( $page < 1 )
{
$page = 1;
}
/* Run */
$results = \IPS\Db::i()->union( $selects, 'date DESC', array( ( ( $page - 1 ) * 25 ), 25 ), ( $onlyFollowed ) ? '_app, _follow_area, id' : NULL, FALSE, \IPS\Db::SELECT_SQL_CALC_FOUND_ROWS, $where );
/* Joins */
if ( $onlyFollowed )
{
$results->join( 'core_follow', "follow_app=_app AND follow_area=_follow_area AND follow_rel_id=id" );
}
$resultPages = ceil( $results->count( TRUE ) / 25 );
/* Build a table */
$table = new \IPS\Helpers\Table\Custom( iterator_to_array( $results ), $baseUrl );
$table->classes[] = 'ipsDataList_zebra';
$table->pages = $resultPages;
$table->rowsTemplate = array( \IPS\Theme::i()->getTemplate( 'vnc' ), 'genericRows' );
}
/* Display */
if ( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->json( array(
'sidebar' => \IPS\Theme::i()->getTemplate('vnc')->filters( $baseUrl, $types, $nodeSelect, $nodeTitle ),
'content' => \IPS\Theme::i()->getTemplate('vnc')->results( $baseUrl, (string) $table, \IPS\Request::i()->vncTimePeriod, $interval, $start, $end ?: \IPS\DateTime::create() ),
) );
}
else
{
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js('front_vnc.js', 'core' ) );
\IPS\Output::i()->sidebar['enabled'] = FALSE;
\IPS\Output::i()->breadcrumb[] = array( NULL, \IPS\Member::loggedIn()->language()->addToStack('search_vnc_title') );
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('search_vnc_title');
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('vnc')->template( $baseUrl, $types, (string) $table, \IPS\Request::i()->vncTimePeriod, $interval, $start, $end ?: \IPS\DateTime::create(), $nodeSelect, $nodeTitle );
}
}
/**
* Get the 'unread' where SQL
*
* @param string $class Content class (\IPS\forums\Forum)
* @return array
*/
protected function _getUnreadWhere( $class )
{
$classBits = explode( "\\", $class );
$application = $classBits[1];
$resetTimes = \IPS\Member::loggedIn()->markersResetTimes( $application );
$oldestTime = time();
$markers = array();
$excludeIds = array();
$where = array();
$unreadWheres = array();
$containerIds = array();
$containerClass = ( $class::$containerNodeClass ) ? $class::$containerNodeClass : NULL;
/* What is the best date column? */
$dateColumns = array();
foreach ( array( 'updated', 'last_comment', 'last_review' ) as $k )
{
if ( isset( $class::$databaseColumnMap[ $k ] ) )
{
if ( is_array( $class::$databaseColumnMap[ $k ] ) )
{
foreach ( $class::$databaseColumnMap[ $k ] as $v )
{
$dateColumns[] = " IFNULL( " . $class::$databaseTable . '.'. $class::$databasePrefix . $v . ", 0 )";
}
}
else
{
$dateColumns[] = " IFNULL( " . $class::$databaseTable . '.'. $class::$databasePrefix . $class::$databaseColumnMap[ $k ] . ", 0 )";
}
}
}
$dateColumnExpression = count( $dateColumns ) > 1 ? ( 'GREATEST(' . implode( ',', $dateColumns ) . ')' ) : array_pop( $dateColumns );
foreach( $resetTimes as $containerId => $timestamp )
{
$container = NULL;
if( $containerId AND $containerClass )
{
try
{
$container = $containerClass::load( $containerId );
}
catch ( \OutOfRangeException $e)
{
continue;
}
}
$timestamp = $timestamp ?: \IPS\Member::loggedIn()->marked_site_read;
$containerIds[] = $containerId;
$unreadWheres[] = '( ' . $class::$databaseTable . '.' . $class::$databasePrefix . $class::$databaseColumnMap['container'] . '=' . $containerId . ' AND ' . $dateColumnExpression . ' > ' . (int) $timestamp . ')';
$items = \IPS\Member::loggedIn()->markersItems( $application, \IPS\Content\Item::makeMarkerKey( $container ) );
if ( count( $items ) )
{
foreach( $items as $mid => $mtime )
{
if ( $mtime > $timestamp )
{
$markers[ $mtime . '.' . $mid ] = $mid;
}
}
}
}
if( count( $containerIds ) )
{
$unreadWheres[] = "( " . $dateColumnExpression . " > " . \IPS\Member::loggedIn()->marked_site_read . " AND ( " . $class::$databaseTable . '.' . $class::$databasePrefix . $class::$databaseColumnMap['container'] . " NOT IN(" . implode( ',', $containerIds ) . ") ) )";
}
else
{
$unreadWheres[] = "( " . $dateColumnExpression . " > " . \IPS\Member::loggedIn()->marked_site_read . ")";
}
if( count( $unreadWheres ) )
{
$where[] = array( "(" . implode( " OR ", $unreadWheres ) . ")" );
}
if ( count( $markers ) )
{
/* Avoid packet issues */
krsort( $markers );
$useIds = array_flip( array_slice( $markers, 0, 500, TRUE ) );
$select = '';
$from = '';
$notIn = array();
foreach( \IPS\Db::i()->select( $class::$databaseTable . '.' . $class::$databasePrefix . $class::$databaseColumnId. ' as _id, ' . $dateColumnExpression . ' as _date', $class::$databaseTable, \IPS\Db::i()->in( $class::$databasePrefix . $class::$databaseColumnId, array_keys( $useIds ) ) ) as $row )
{
if ( isset( $useIds[ $row['_id'] ] ) )
{
if ( $useIds[ $row['_id'] ] >= $row['_date'] )
{
/* Still read */
$notIn[] = intval( $row['_id'] );
}
}
}
if ( count( $notIn ) )
{
$where[] = array( "( " . $class::$databaseTable . '.' . $class::$databasePrefix . $class::$databaseColumnId . " NOT IN (" . implode( ',', $notIn ) . ") )" );
}
}
return $where;
}
/**
* Get the date Column expression
*
* @param string $class Content class (\IPS\forums\Forum)
* @return string
*/
protected function _getDateExpression( $class )
{
/* What is the best date column? */
$dateColumns = array();
foreach ( array( 'updated', 'last_comment', 'last_review' ) as $k )
{
if ( isset( $class::$databaseColumnMap[ $k ] ) )
{
if ( is_array( $class::$databaseColumnMap[ $k ] ) )
{
foreach ( $class::$databaseColumnMap[ $k ] as $v )
{
$dateColumns[] = " IFNULL( " . $class::$databaseTable . '.'. $class::$databasePrefix . $v . ", 0 )";
}
}
else
{
$dateColumns[] = " IFNULL( " . $class::$databaseTable . '.'. $class::$databasePrefix . $class::$databaseColumnMap[ $k ] . ", 0 )";
}
}
}
return count( $dateColumns ) > 1 ? ( 'GREATEST(' . implode( ',', $dateColumns ) . ')' ) : array_pop( $dateColumns );
}
}