Version 4.1.19
This commit is contained in:
1 parent
28bd025b35
commit
2bd5025018
2674 files changed
+233518
-77766
No files matched your search
@@ -0,0 +1,563 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Popular things
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @since 21 Oct 2016
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\discover;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Most popular things
|
||||
*/
|
||||
class _popular extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
/* Ensure that the rep system is enabled and the leaderboard is enabled */
|
||||
if ( ! \IPS\Settings::i()->reputation_enabled or ! \IPS\Settings::i()->reputation_leaderboard_on )
|
||||
{
|
||||
\IPS\Output::i()->error( 'module_no_permission', '2C343/1', 403, '' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/search.css' ) );
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/leaderboard.css' ) );
|
||||
|
||||
if ( \IPS\Theme::i()->settings['responsive'] )
|
||||
{
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/search_responsive.css' ) );
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/leaderboard_responsive.css' ) );
|
||||
}
|
||||
|
||||
/* Make sure default tab is first */
|
||||
$tabs = array( \IPS\Settings::i()->reputation_leaderboard_default_tab );
|
||||
|
||||
foreach( array( 'leaderboard', 'history', 'members' ) as $addTab )
|
||||
{
|
||||
if ( $addTab != \IPS\Settings::i()->reputation_leaderboard_default_tab )
|
||||
{
|
||||
$tabs[] = $addTab;
|
||||
}
|
||||
}
|
||||
|
||||
$activeTab = ( isset( \IPS\Request::i()->tab ) and in_array(\IPS\Request::i()->tab, $tabs ) ) ? \IPS\Request::i()->tab : \IPS\Settings::i()->reputation_leaderboard_default_tab;
|
||||
|
||||
/* Initiate the breadcrumb */
|
||||
\IPS\Output::i()->breadcrumb = array( array( \IPS\Http\Url::internal( "app=core&module=discover&controller=popular&tab=" . $activeTab, 'front', 'leaderboard_' . $activeTab ), \IPS\Member::loggedIn()->language()->addToStack('leaderboard_title') ) );
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'leaderboard_tabs_' . $activeTab );
|
||||
|
||||
$content = $this->$activeTab();
|
||||
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->blankTemplate( $content ), 200, 'text/html', \IPS\Output::i()->httpHeaders );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Display */
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('popular')->tabs( $tabs, $activeTab, $content );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* View top members
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function members()
|
||||
{
|
||||
$filters = array(
|
||||
'reputation' => array( 'pp_reputation_points', \IPS\Member::loggedIn()->language()->addToStack('leaderboard_tab_reputation') ),
|
||||
'posts' => array( 'member_posts', \IPS\Member::loggedIn()->language()->addToStack('leaderboard_tab_posts') )
|
||||
);
|
||||
|
||||
$classes = array();
|
||||
foreach ( \IPS\Application::allExtensions( 'core', 'ContentRouter', TRUE ) as $object )
|
||||
{
|
||||
$classes = array_merge( $object->classes, $classes );
|
||||
}
|
||||
|
||||
foreach( $classes as $item )
|
||||
{
|
||||
$commentClass = NULL;
|
||||
|
||||
if ( isset( $item::$commentClass ) )
|
||||
{
|
||||
$commentClass = $item::$commentClass;
|
||||
}
|
||||
|
||||
if ( $item::$firstCommentRequired and isset( $commentClass::$databaseColumnMap['author'] ) )
|
||||
{
|
||||
$filters[ 'app_' . $item::$application . '_' . $item::$module ] = array(
|
||||
$commentClass,
|
||||
\IPS\Member::loggedIn()->language()->addToStack('leaderboard_tab_x', NULL, array( 'sprintf' => array( \IPS\Member::loggedIn()->language()->addToStack("{$commentClass::$title}_pl_lc") ) ) ),
|
||||
\IPS\Member::loggedIn()->language()->addToStack("{$commentClass::$title}_pl")
|
||||
);
|
||||
}
|
||||
else if ( isset( $item::$databaseColumnMap['author'] ) )
|
||||
{
|
||||
$filters[ 'app_' . $item::$application . '_' . $item::$module ] = array(
|
||||
$item,
|
||||
\IPS\Member::loggedIn()->language()->addToStack('leaderboard_tab_x', NULL, array( 'sprintf' => array( \IPS\Member::loggedIn()->language()->addToStack("{$item::$title}_pl_lc") ) ) ),
|
||||
\IPS\Member::loggedIn()->language()->addToStack("{$item::$title}_pl")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$activeFilter = ( isset( \IPS\Request::i()->filter ) and isset( $filters[ \IPS\Request::i()->filter ] ) ) ? \IPS\Request::i()->filter : 'reputation';
|
||||
$members = array();
|
||||
|
||||
/* Get the members */
|
||||
if ( mb_substr( $activeFilter, 0, 4 ) == 'app_' )
|
||||
{
|
||||
$storeKey = 'store_' . $activeFilter;
|
||||
$recache = true;
|
||||
$memberIds = NULL;
|
||||
|
||||
if ( isset( \IPS\Data\Store::i()->$storeKey ) )
|
||||
{
|
||||
$cache = \IPS\Data\Store::i()->$storeKey;
|
||||
|
||||
if ( isset( $cache['time'] ) and isset( $cache['memberIds'] ) and ( time() - $cache['time'] < 300 ) )
|
||||
{
|
||||
$memberIds = $cache['memberIds'];
|
||||
}
|
||||
}
|
||||
|
||||
/* Nothing returned from the cache, so fetch and store */
|
||||
if ( $memberIds === NULL )
|
||||
{
|
||||
$class = $filters[ $activeFilter ][0];
|
||||
$authorField = $class::$databasePrefix . $class::$databaseColumnMap['author'];
|
||||
$memberIds = array();
|
||||
$where = NULL;
|
||||
|
||||
if ( isset( $class::$databaseColumnMap['hidden'] ) )
|
||||
{
|
||||
$where = array( $class::$databasePrefix . $class::$databaseColumnMap['hidden'] . '=0' );
|
||||
}
|
||||
else if ( isset( $class::$databaseColumnMap['approved'] ) )
|
||||
{
|
||||
$where = array( $class::$databasePrefix . $class::$databaseColumnMap['approved'] . '=1' );
|
||||
}
|
||||
|
||||
/* Get member IDS */
|
||||
foreach( \IPS\Db::i()->select( 'COUNT(*) as count, ' . $class::$databaseTable . '.' . $authorField, $class::$databaseTable, $where, 'count DESC', array( 0, \IPS\Settings::i()->reputation_max_members ), $authorField ) as $row )
|
||||
{
|
||||
$memberIds[ $row[ $authorField ] ] = array( $row['count'] . '.' . $row[ $authorField ], $row['count'] );
|
||||
}
|
||||
|
||||
\IPS\Data\Store::i()->$storeKey = array( 'time' => time(), 'memberIds' => $memberIds );
|
||||
}
|
||||
|
||||
if ( count( $memberIds ) )
|
||||
{
|
||||
foreach( \IPS\Db::i()->select( '*', 'core_members', array( \IPS\Db::i()->in( 'member_id', array_keys( $memberIds ) ) ) ) as $member )
|
||||
{
|
||||
$members[ $memberIds[ $member['member_id'] ][0] ] = \IPS\Member::constructFromData( array_merge( $member, array( 'custom_count' => $memberIds[ $member['member_id'] ][1] ) ) );
|
||||
}
|
||||
|
||||
krsort( $members );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$members = iterator_to_array( new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'core_members', array( "name IS NOT NULL AND name != '' AND temp_ban != -1 AND email != '' AND " . $filters[ $activeFilter ][0] . " > 0" ), $filters[ $activeFilter ][0] . ' DESC', array( 0, \IPS\Settings::i()->reputation_max_members ) ), '\IPS\Member' ) );
|
||||
}
|
||||
|
||||
$contentLabel = 'members_member_posts';
|
||||
$contentCount = 'member_posts';
|
||||
if ( isset( $filters[ $activeFilter ][2] ) )
|
||||
{
|
||||
$contentLabel = $filters[ $activeFilter ][2];
|
||||
$contentCount = 'custom_count';
|
||||
}
|
||||
|
||||
if ( \IPS\Request::i()->isAjax() and \IPS\Request::i()->topMembers )
|
||||
{
|
||||
\IPS\Output::i()->json( array( 'rows' => \IPS\Theme::i()->getTemplate('popular')->membersWrapper( $members, $contentLabel, $contentCount ), 'extraHtml' => $filters[ $activeFilter ][1] ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate('popular')->members( $members, $filters, $activeFilter, \IPS\Http\Url::internal( "app=core&module=discover&controller=popular&tab=members", 'front', 'leaderboard_members' ), $contentLabel, $contentCount );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* View past leaders
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function history()
|
||||
{
|
||||
$table = new \IPS\Helpers\Table\Db( 'core_reputation_leaderboard_history', \IPS\Http\Url::internal( "app=core&module=discover&controller=popular&tab=history", 'front', 'leaderboard_history' ) );
|
||||
$table->where = array( 'leader_position <= 3' );
|
||||
$table->limit = 21;
|
||||
$table->selects = array( 'leader_member_id, leader_position, leader_rep_total', 'ABS(leader_date - leader_position) as leader_date' );
|
||||
$table->joins = array( array( 'select' => 'core_members.*', 'from' => 'core_members', 'where' => 'core_reputation_leaderboard_history.leader_member_id=core_members.member_id' ) );
|
||||
$table->include = array( 'leader_member_id', 'leader_date', 'leader_position', 'leader_rep_total' );
|
||||
$table->noSort = array( 'leader_member_id', 'leader_position', 'leader_rep_total' );
|
||||
$table->tableTemplate = array( \IPS\Theme::i()->getTemplate( 'popular', 'core', 'front' ), 'popularTable' );
|
||||
$table->rowsTemplate = array( \IPS\Theme::i()->getTemplate( 'popular', 'core', 'front' ), 'popularRows' );
|
||||
$table->title = 'leaderboard_history';
|
||||
$table->mainColumn = 'leader_date';
|
||||
$table->sortBy = $table->sortBy ?: 'leader_date';
|
||||
$table->sortDirection = $table->sortDirection ?: 'DESC';
|
||||
|
||||
/* Like or what? */
|
||||
if ( \IPS\Settings::i()->reputation_point_types == 'like' )
|
||||
{
|
||||
\IPS\Member::loggedIn()->language()->words['leader_rep_total'] = \IPS\Member::loggedIn()->language()->addToStack( 'leader_rep_total_likes' );
|
||||
\IPS\Member::loggedIn()->language()->words['leaderboard_history__desc'] = \IPS\Member::loggedIn()->language()->addToStack( 'leaderboard_history_desc', NULL, array( 'sprintf' => array( \IPS\Member::loggedIn()->language()->addToStack( 'leaderboard_history_likes') ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Member::loggedIn()->language()->words['leader_rep_total'] = \IPS\Member::loggedIn()->language()->addToStack( 'leader_rep_total_rep' );
|
||||
\IPS\Member::loggedIn()->language()->words['leaderboard_history__desc'] = \IPS\Member::loggedIn()->language()->addToStack( 'leaderboard_history_desc', NULL, array( 'sprintf' => array( \IPS\Member::loggedIn()->language()->addToStack( 'leaderboard_history_rep') ) ) );
|
||||
}
|
||||
|
||||
/* Parsers */
|
||||
$table->parsers = array(
|
||||
'leader_member_id' => function( $val, $row )
|
||||
{
|
||||
return \IPS\Member::constructFromData( $row );
|
||||
},
|
||||
'leader_date' => function( $val )
|
||||
{
|
||||
return \IPS\DateTime::ts( $val )->setTimezone( new \DateTimeZone( \IPS\Settings::i()->reputation_timezone ) );
|
||||
}
|
||||
);
|
||||
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->blankTemplate( $table ), 200, 'text/html', \IPS\Output::i()->httpHeaders );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( $table->page > 1 )
|
||||
{
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'title_with_page_number', FALSE, array( 'sprintf' => array( \IPS\Output::i()->title, $table->page ) ) );
|
||||
}
|
||||
|
||||
return (string) $table;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* View Popular list
|
||||
*
|
||||
* It's slightly cumbersome because we need to group, but we can only select columns in the group list, so we have to:
|
||||
* 1) Fetch the lookup_hash and total_rep
|
||||
* 2) Fetch the rep data so we can...
|
||||
* 3) Fetch the search engine data and then...
|
||||
* 4) Manually sort in PHP
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function leaderboard()
|
||||
{
|
||||
/* Figure out dates */
|
||||
$dates = array();
|
||||
$timezone = new \DateTimeZone( \IPS\Settings::i()->reputation_timezone );
|
||||
$endDate = \IPS\DateTime::ts( time() )->setTimezone( $timezone );
|
||||
|
||||
$firstRepDate = \IPS\Db::i()->select( 'MIN(rep_date)', 'core_reputation_index' )->first();
|
||||
$firstIndexDate = \IPS\Db::i()->select( 'MIN(index_date_updated)', 'core_search_index' )->first();
|
||||
$appWhere = null;
|
||||
$descApp = \IPS\Member::loggedIn()->language()->addToStack('leaderboard_in_all_apps');
|
||||
|
||||
$dates['oldest'] = \IPS\DateTime::ts( ( $firstRepDate > $firstIndexDate ) ? $firstRepDate : $firstIndexDate );
|
||||
$oldestStamp = $dates['oldest']->getTimeStamp();
|
||||
$date = $dates['oldest'];
|
||||
|
||||
$aYearAgo = \IPS\DateTime::create()->setTimezone( $timezone )->sub( new \DateInterval( 'P1Y' ) );
|
||||
$month = \IPS\DateTime::create()->setTimezone( $timezone )->sub( new \DateInterval( 'P1M' ) )->setTime( 0, 0 );
|
||||
$week = \IPS\DateTime::create()->setTimezone( $timezone )->sub( new \DateInterval( 'P7D' ) )->setTime( 0, 0 );
|
||||
$today = \IPS\DateTime::create()->setTimezone( $timezone )->setTime( 0, 0 );
|
||||
|
||||
if ( $aYearAgo->getTimeStamp() > $oldestStamp )
|
||||
{
|
||||
$dates['year'] = $aYearAgo;
|
||||
}
|
||||
|
||||
if ( $month->getTimeStamp() > $oldestStamp )
|
||||
{
|
||||
$dates['month'] = $month;
|
||||
}
|
||||
|
||||
if ( $week->getTimeStamp() > $oldestStamp )
|
||||
{
|
||||
$dates['week'] = $week;
|
||||
}
|
||||
|
||||
if ( $today->getTimeStamp() > $oldestStamp )
|
||||
{
|
||||
$dates['today'] = $today;
|
||||
}
|
||||
|
||||
/* Got a date? */
|
||||
if ( isset( \IPS\Request::i()->time ) and isset( $dates[ \IPS\Request::i()->time ] ) )
|
||||
{
|
||||
$date = $dates[ \IPS\Request::i()->time ];
|
||||
}
|
||||
else if ( isset( $dates['month'] ) )
|
||||
{
|
||||
/* Set the default to month */
|
||||
\IPS\Request::i()->time = 'month';
|
||||
$date = $dates['month'];
|
||||
}
|
||||
|
||||
/* Applications */
|
||||
$classes = array();
|
||||
foreach ( \IPS\Application::allExtensions( 'core', 'ContentRouter', TRUE ) as $object )
|
||||
{
|
||||
$classes = array_merge( $object->classes, $classes );
|
||||
}
|
||||
|
||||
$areas = array();
|
||||
foreach( $classes as $item )
|
||||
{
|
||||
$commentClass = NULL;
|
||||
$reviewClass = NULL;
|
||||
|
||||
if ( in_array( 'IPS\Content\Reputation', class_implements( $item ) ) and isset( $item::$reputationType ) )
|
||||
{
|
||||
$areas[ $item::$application . '-' . $item::$reputationType ] = array( $item, \IPS\Member::loggedIn()->language()->addToStack("{$item::$title}_pl") );
|
||||
}
|
||||
|
||||
if ( isset( $item::$commentClass ) )
|
||||
{
|
||||
$commentClass = $item::$commentClass;
|
||||
if ( in_array( 'IPS\Content\Reputation', class_implements( $commentClass ) ) and isset( $commentClass::$reputationType ) )
|
||||
{
|
||||
$areas[ $item::$application . '-' . $commentClass::$reputationType ] = array( $commentClass, \IPS\Member::loggedIn()->language()->addToStack("{$commentClass::$title}_pl") );
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $item::$reviewClass ) )
|
||||
{
|
||||
$reviewClass = $item::$reviewClass;
|
||||
if ( in_array( 'IPS\Content\Reputation', class_implements( $reviewClass ) ) and isset( $reviewClass::$reputationType ) )
|
||||
{
|
||||
$areas[ $item::$application . '-' . $reviewClass::$reputationType ] = array( $reviewClass, \IPS\Member::loggedIn()->language()->addToStack("{$reviewClass::$title}_pl") );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form('popular_date', 'continue');
|
||||
$form->class = 'ipsForm_vertical';
|
||||
$customStart = isset( \IPS\Request::i()->custom_date_start ) ? \IPS\Request::i()->custom_date_start : NULL;
|
||||
$customEnd = isset( \IPS\Request::i()->custom_date_end ) ? \IPS\Request::i()->custom_date_end : NULL;
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\DateRange( 'custom_date', array( 'start' => $customStart, 'end' => $customEnd ), FALSE, array( 'start' => array( 'min' => $dates['oldest'], 'time' => false ) ) ) );
|
||||
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$url = \IPS\Request::i()->url()->stripQueryString('time');
|
||||
|
||||
if ( isset( $values['custom_date']['start'] ) and $values['custom_date']['start'] instanceof \IPS\DateTime )
|
||||
{
|
||||
$url = $url->setQueryString( 'custom_date_start', $values['custom_date']['start']->getTimeStamp() );
|
||||
}
|
||||
|
||||
if ( isset( $values['custom_date']['end'] ) and $values['custom_date']['end'] instanceof \IPS\DateTime )
|
||||
{
|
||||
$url = $url->setQueryString( 'custom_date_end', $values['custom_date']['end']->getTimeStamp() );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( $url );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( $customStart )
|
||||
{
|
||||
$date = \IPS\DateTime::ts( $customStart )->setTimezone( $timezone )->setTime( 0, 0, 1 );
|
||||
}
|
||||
|
||||
if ( $customEnd )
|
||||
{
|
||||
$endDate = \IPS\DateTime::ts( $customEnd )->setTimezone( $timezone )->setTime( 23, 59, 59 );
|
||||
}
|
||||
}
|
||||
|
||||
/* Got an app? */
|
||||
$appWhere = '';
|
||||
|
||||
if ( isset( \IPS\Request::i()->in ) and isset( $areas[ \IPS\Request::i()->in ] ) )
|
||||
{
|
||||
$appWhere = " AND rep_class='" . \IPS\Db::i()->escape_string( $areas[ \IPS\Request::i()->in ][0] ) . "'";
|
||||
$descApp = \IPS\Member::loggedIn()->language()->addToStack('leaderboard_in_app', NULL, array( 'sprintf' => array( $areas[ \IPS\Request::i()->in ][1] ) ) );
|
||||
}
|
||||
|
||||
$storeKey = NULL;
|
||||
$hashes = NULL;
|
||||
if ( ! $customStart and ! $customEnd AND ! $appWhere )
|
||||
{
|
||||
$storeKey = 'leaderHashes_' . \IPS\Request::i()->time . '-' . md5( implode( ',', \IPS\Member::loggedIn()->groups ) );
|
||||
|
||||
if ( isset( \IPS\Data\Store::i()->$storeKey ) )
|
||||
{
|
||||
$stored = \IPS\Data\Store::i()->$storeKey;
|
||||
|
||||
if ( isset( $stored['hashes'] ) and isset( $stored['time'] ) and $stored['time'] > ( time() - 900 ) )
|
||||
{
|
||||
$hashes = $stored['hashes'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Get hashes and total rep */
|
||||
if ( $hashes === NULL )
|
||||
{
|
||||
/* Prevent race condition */
|
||||
if ( $storeKey )
|
||||
{
|
||||
\IPS\Data\Store::i()->$storeKey = array( 'time' => time(), 'hashes' => array() );
|
||||
}
|
||||
|
||||
$testFirst = iterator_to_array( \IPS\Db::i()->select( 'class_type_id_hash', 'core_reputation_index', array( 'rep_date BETWEEN ' . $date->getTimeStamp() . ' AND ' . $endDate->getTimeStamp() . $appWhere ), NULL, NULL, 'class_type_id_hash' ) );
|
||||
$searchWhere = array( array( "( si.index_permissions = '*' OR " . \IPS\Db::i()->findInSet( 'si.index_permissions', \IPS\Member::loggedIn()->groups ) . ' AND si.index_hidden=0 )' ) );
|
||||
|
||||
if ( count( $testFirst ) < 501 )
|
||||
{
|
||||
/* We can use an IN() to make this a bit more efficient */
|
||||
$repQuery = \IPS\Db::i()->select( 'class_type_id_hash, SUM(rep_rating) as total_rep', 'core_reputation_index', \IPS\Db::i()->in( 'class_type_id_hash', array_values( $testFirst ) ), NULL, NULL, 'class_type_id_hash' );
|
||||
|
||||
$searchWhere[] = array( \IPS\Db::i()->in( 'si.index_class_type_id_hash', array_values( $testFirst ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
$repQuery = \IPS\Db::i()->select( 'class_type_id_hash, SUM(rep_rating) as total_rep', 'core_reputation_index', array( 'rep_date BETWEEN ' . $date->getTimeStamp() . ' AND ' . $endDate->getTimeStamp() . $appWhere ), NULL, NULL, 'class_type_id_hash' );
|
||||
}
|
||||
|
||||
$searchQuery = \IPS\Db::i()->select( 'index_class_type_id_hash', array( 'core_search_index', 'si' ), $searchWhere );
|
||||
|
||||
$hashes = iterator_to_array(
|
||||
\IPS\Db::i()->select( 'class_type_id_hash, total_rep', array( $repQuery, 'ri' ), array( 'class_type_id_hash IN(?)', $searchQuery ), 'total_rep DESC', array( 0, 50 ) )->setKeyField('class_type_id_hash')
|
||||
);
|
||||
|
||||
if ( $storeKey )
|
||||
{
|
||||
\IPS\Data\Store::i()->$storeKey = array( 'time' => time(), 'hashes' => $hashes );
|
||||
}
|
||||
}
|
||||
|
||||
$classes = array();
|
||||
$repData = array();
|
||||
$or = array();
|
||||
$results = array();
|
||||
$preLoadMembers = array();
|
||||
|
||||
if ( count( $hashes ) )
|
||||
{
|
||||
/* Now get the reputation data */
|
||||
foreach( \IPS\Db::i()->select( '*', 'core_reputation_index', array( \IPS\Db::i()->in( 'class_type_id_hash', array_keys( $hashes ) ) ) ) as $data )
|
||||
{
|
||||
$data['total_rep'] = $hashes[ $data['class_type_id_hash'] ]['total_rep'];
|
||||
$repData[ $data['rep_class'] . '-' . $data['type_id'] ] = $data;
|
||||
$classes[ $data['rep_class'] ][] = $data['type_id'];
|
||||
|
||||
if ( ! empty( $data['member_id'] ) )
|
||||
{
|
||||
$preLoadMembers[] = $data['member_id'];
|
||||
}
|
||||
}
|
||||
|
||||
foreach( $classes as $class => $ids )
|
||||
{
|
||||
$or[] = '( index_class=\'' . \IPS\Db::i()->escape_string( $class ) . '\' AND ' . \IPS\Db::i()->in( 'index_object_id', $ids ) . ')';
|
||||
}
|
||||
|
||||
/* Construct the query */
|
||||
$query = \IPS\Db::i()->select( '*', array( 'core_search_index', 'main' ), array( implode( ' OR ', $or ) ), NULL, NULL, NULL, NULL );
|
||||
|
||||
$array = iterator_to_array( $query );
|
||||
$sorted = array();
|
||||
|
||||
/* Manually sort */
|
||||
foreach( $array as $index => $data )
|
||||
{
|
||||
if ( isset( $repData[ $data['index_class'] . '-' . $data['index_object_id'] ] ) )
|
||||
{
|
||||
$data['rep_data'] = $repData[ $data['index_class'] . '-' . $data['index_object_id'] ];
|
||||
$sorted[ $data['rep_data']['total_rep'] . '.' . $data['index_date_updated'] . '.'. $index ] = $data;
|
||||
}
|
||||
}
|
||||
unset( $array );
|
||||
krsort( $sorted, SORT_NUMERIC );
|
||||
|
||||
$results = new \IPS\Content\Search\Results( $sorted, count( $sorted ) );
|
||||
|
||||
/* Load data we need like the authors, etc */
|
||||
$results->init();
|
||||
}
|
||||
|
||||
/* Get top rated contributors */
|
||||
$topContributors = array();
|
||||
|
||||
$innerQuery = \IPS\Db::i()->select( 'core_reputation_index.member_received as member, SUM(rep_rating) as rep', 'core_reputation_index', array( 'member_received>0 ' . $appWhere . ' and rep_date BETWEEN ' . intval( $date->getTimeStamp() ) . ' AND ' . intval( $endDate->getTimeStamp() ) ), NULL, NULL, 'member' );
|
||||
foreach( \IPS\Db::i()->select( 'member, rep', array( $innerQuery, 'in' ), NULL, 'rep DESC', 4 )->setKeyField('member')->setValueField('rep') as $member => $rep )
|
||||
{
|
||||
$topContributors[ $member ] = $rep;
|
||||
}
|
||||
|
||||
if ( count( $topContributors ) )
|
||||
{
|
||||
$preLoadMembers = array_merge( $preLoadMembers, array_keys( $topContributors ) );
|
||||
}
|
||||
|
||||
/* Load their data */
|
||||
if ( count( $preLoadMembers ) )
|
||||
{
|
||||
foreach ( \IPS\Db::i()->select( '*', 'core_members', \IPS\Db::i()->in( 'member_id', array_unique( $preLoadMembers ) ) ) as $member )
|
||||
{
|
||||
\IPS\Member::constructFromData( $member );
|
||||
}
|
||||
}
|
||||
|
||||
/* Work out the description for popular content */
|
||||
if ( \IPS\Settings::i()->reputation_point_types == 'like' )
|
||||
{
|
||||
$popularResultsSingle = 'popular_results_single_desc';
|
||||
$popularResultsMany = 'popular_results_desc';
|
||||
}
|
||||
else
|
||||
{
|
||||
$popularResultsSingle = 'popular_results_single_desc_rep';
|
||||
$popularResultsMany = 'popular_results_desc_rep';
|
||||
}
|
||||
|
||||
$description = \IPS\Member::loggedIn()->language()->addToStack( ( $date->localeDate() == $endDate->localeDate() ) ? $popularResultsSingle : $popularResultsMany, NULL, array( 'sprintf' => array( $date->localeDate(), $descApp ) ) );
|
||||
|
||||
/* Are our offsets different? */
|
||||
$tzOffsetDifference = NULL;
|
||||
try
|
||||
{
|
||||
if ( \IPS\DateTime::ts( time() )->getOffset() != \IPS\DateTime::ts( time() )->setTimezone( $timezone )->getOffset() )
|
||||
{
|
||||
$tzOffsetDifference = \IPS\DateTime::ts( time() )->setTimezone( $timezone )->format('P');
|
||||
}
|
||||
}
|
||||
catch( \Exception $ex ) { }
|
||||
|
||||
/* Display */
|
||||
return \IPS\Theme::i()->getTemplate('popular')->popularWrapper( $results, $areas, $topContributors, $dates, $description, $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupTemplate' ) ), $tzOffsetDifference );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief rss
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
|
||||
* @since 13 Oct 2016
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\discover;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* rss
|
||||
*/
|
||||
class _rss extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* Display Feed
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
{
|
||||
try
|
||||
{
|
||||
$feed = \IPS\core\Rss::load( \IPS\Request::i()->id );
|
||||
}
|
||||
catch( \OutOfRangeException $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C340/1', 404, '' );
|
||||
}
|
||||
|
||||
if ( !$feed->_enabled )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error_no_perm', '2C340/2', 403, '' );
|
||||
}
|
||||
|
||||
/* Specific Member? */
|
||||
if ( isset( \IPS\Request::i()->member_id ) AND isset( \IPS\Request::i()->key ) )
|
||||
{
|
||||
/* Load Member */
|
||||
$member = \IPS\Member::load( \IPS\Request::i()->member_id );
|
||||
|
||||
/* Make sure we have an actual member, and that the key matches. If it doesn't, we can bubble up and see if the feed works for guests, and just use that */
|
||||
if ( $member->member_id AND \IPS\Login::compareHashes( (string) \IPS\Request::i()->key, md5( $member->member_id . $member->email . $member->member_pass_hash . $member->member_pass_salt ) ) )
|
||||
{
|
||||
/* Make sure we have access to this feed. */
|
||||
if ( $feed->groups == '*' OR $member->inGroup( $feed->groups ) )
|
||||
{
|
||||
/* Send It */
|
||||
\IPS\Output::i()->sendOutput( $feed->generate( $member ), 200, 'text/xml' );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error_no_perm', '2C340/3', 403, '' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* We're working with a guest. */
|
||||
if ( $feed->groups == '*' OR in_array( \IPS\Settings::i()->guest_group, $feed->groups ) )
|
||||
{
|
||||
\IPS\Output::i()->sendOutput( $feed->generate(), 200, 'text/xml' );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error_no_perm', '2C340/4', 403, '' );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief streams
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Social Suite
|
||||
* @package IPS Community Suite
|
||||
* @since 02 Jul 2015
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -30,13 +30,23 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
if ( isset( \IPS\Request::i()->_nodeSelectName ) )
|
||||
{
|
||||
return $this->getContainerNodeElement();
|
||||
}
|
||||
|
||||
/* Initiate the breadcrumb */
|
||||
\IPS\Output::i()->breadcrumb = array( array( \IPS\Http\Url::internal( "app=core&module=discovery&controller=streams", 'front', 'discover_all' ), \IPS\Member::loggedIn()->language()->addToStack('activity') ) );
|
||||
\IPS\Output::i()->breadcrumb = array( array( \IPS\Http\Url::internal( "app=core&module=discover&controller=streams", 'front', 'discover_all' ), \IPS\Member::loggedIn()->language()->addToStack('activity') ) );
|
||||
|
||||
/* Necessary CSS/JS */
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js('front_streams.js', 'core' ) );
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/streams.css' ) );
|
||||
|
||||
if ( \IPS\Theme::i()->settings['responsive'] )
|
||||
{
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/streams_responsive.css', 'core', 'front' ) );
|
||||
}
|
||||
|
||||
/* Execute */
|
||||
return parent::execute();
|
||||
}
|
||||
@@ -49,11 +59,25 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
protected function manage()
|
||||
{
|
||||
/* If this request is from an auto-poll, kill it and exit */
|
||||
if ( !\IPS\Settings::i()->auto_polling_enabled && \IPS\Request::i()->isAjax() and isset( \IPS\Request::i()->after ) ){
|
||||
if ( !\IPS\Settings::i()->auto_polling_enabled && \IPS\Request::i()->isAjax() and isset( \IPS\Request::i()->after ) )
|
||||
{
|
||||
\IPS\Output::i()->json( array( 'error' => 'auto_polling_disabled' ) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* RSS validate? */
|
||||
$member = NULL;
|
||||
|
||||
if ( isset( \IPS\Request::i()->rss ) )
|
||||
{
|
||||
$member = \IPS\Member::load( \IPS\Request::i()->member );
|
||||
if ( !\IPS\Login::compareHashes( md5( ( $member->members_pass_hash ?: $member->email ) . $member->members_pass_salt ), (string) \IPS\Request::i()->key ) )
|
||||
{
|
||||
$member = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
$form = NULL;
|
||||
/* Viewing a particular stream? */
|
||||
if ( isset( \IPS\Request::i()->id ) )
|
||||
{
|
||||
@@ -68,15 +92,15 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/* Suitable for guests? */
|
||||
if ( ! \IPS\Member::loggedIn()->member_id and ! ( ( $stream->ownership == 'all' or $stream->ownership == 'custom' ) and $stream->read == 'all' and $stream->follow == 'all' and $stream->date_type != 'last_visit' ) )
|
||||
if ( !\IPS\Member::loggedIn()->member_id and !$member and !( ( $stream->ownership == 'all' or $stream->ownership == 'custom' ) and $stream->read == 'all' and $stream->follow == 'all' and $stream->date_type != 'last_visit' ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'stream_no_permission', '2C280/3', 403, '' );
|
||||
}
|
||||
|
||||
$baseUrl = $stream->url();
|
||||
|
||||
if ( \IPS\Member::loggedIn()->member_id and isset( \IPS\Request::i()->default ) )
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
if ( \IPS\Request::i()->default )
|
||||
{
|
||||
\IPS\Member::loggedIn()->defaultStream = $stream->_id;
|
||||
@@ -97,9 +121,10 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->json( array(
|
||||
'url' => $defaultStream->url(),
|
||||
'title' => $defaultStream->_title,
|
||||
'id' => $defaultStream->_id
|
||||
'url' => $defaultStream->url(),
|
||||
'title' => htmlspecialchars( $defaultStream->_title, ENT_QUOTES | \IPS\HTMLENTITIES, 'UTF-8', FALSE ),
|
||||
'tooltip' => $defaultStream->_title, // We need to pass this individually for the tooltip that shows, but the JS itself will escape any entities
|
||||
'id' => $defaultStream->_id
|
||||
) );
|
||||
}
|
||||
}
|
||||
@@ -107,27 +132,7 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->redirect( $stream->url() );
|
||||
}
|
||||
|
||||
if ( isset( \IPS\Request::i()->form ) )
|
||||
{
|
||||
if ( \IPS\Request::i()->form == 'show' )
|
||||
{
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->sendOutput( $this->_buildForm( $stream ), 200, 'text/html' );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->output = $this->_buildForm( $stream );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We want to process the form */
|
||||
$this->_buildForm( $stream );
|
||||
}
|
||||
}
|
||||
$form = $this->_buildForm( $stream );
|
||||
|
||||
/* Set title and breadcrumb */
|
||||
\IPS\Output::i()->breadcrumb[] = array( $stream->url(), $stream->_title );
|
||||
@@ -139,6 +144,8 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
if ( \IPS\Member::loggedIn()->member_id and isset( \IPS\Request::i()->default ) )
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
if ( \IPS\Request::i()->default )
|
||||
{
|
||||
\IPS\Member::loggedIn()->defaultStream = 0;
|
||||
@@ -159,43 +166,109 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->json( array(
|
||||
'url' => \IPS\Http\Url::internal( "app=core&module=discovery&controller=streams", 'front', 'discover_all' ),
|
||||
'title' => $defaultStream->_title,
|
||||
'url' => \IPS\Http\Url::internal( "app=core&module=discover&controller=streams", 'front', 'discover_all' ),
|
||||
'title' => htmlspecialchars( $defaultStream->_title, ENT_QUOTES | \IPS\HTMLENTITIES, 'UTF-8', FALSE ),
|
||||
'id' => $defaultStream->_id
|
||||
) );
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=discovery&controller=streams", 'front', 'discover_all' ) );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=discover&controller=streams", 'front', 'discover_all' ) );
|
||||
}
|
||||
|
||||
/* Start with a blank stream */
|
||||
$stream = \IPS\core\Stream::allActivityStream();
|
||||
$baseUrl = \IPS\Http\Url::internal( "app=core&module=discovery&controller=streams", 'front', 'discover_all' );
|
||||
|
||||
/* Set the title to "All Activity" */
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('all_activity');
|
||||
}
|
||||
|
||||
/* Changes from Update Only */
|
||||
foreach ( array( 'include_comments', 'classes', 'containers', 'ownership', 'read', 'follow', 'date_type', 'date_start', 'date_end', 'date_relative_days', 'sort' ) as $k )
|
||||
{
|
||||
if ( isset( \IPS\Request::i()->$k ) )
|
||||
{
|
||||
$stream->$k = \IPS\Request::i()->$k;
|
||||
$baseUrl = $baseUrl->setQueryString( $k, \IPS\Request::i()->$k );
|
||||
}
|
||||
}
|
||||
|
||||
/* RSS validate? */
|
||||
$member = NULL;
|
||||
if ( isset( \IPS\Request::i()->rss ) )
|
||||
/* Look for url params that can come from view switch or load more button */
|
||||
/* but only if we haven't submitted the form on this request */
|
||||
if( !\IPS\Request::i()->stream_submitted )
|
||||
{
|
||||
$member = \IPS\Member::load( \IPS\Request::i()->member );
|
||||
if ( \IPS\Request::i()->key != md5( ( $member->members_pass_hash ?: $member->email ) . $member->members_pass_salt ) )
|
||||
$streamFields = array( 'include_comments', 'classes', 'ownership', 'custom_members', 'read', 'follow', 'followed_types', 'date_type', 'date_start', 'date_end', 'date_relative_days', 'sort', 'tags', 'unread_links' );
|
||||
|
||||
/* Build and format field values */
|
||||
$_values = array();
|
||||
foreach ( \IPS\Request::i() as $requestKey => $requestField )
|
||||
{
|
||||
$member = NULL;
|
||||
$field = str_replace( 'stream_', '', $requestKey );
|
||||
|
||||
if ( $field == 'custom_members' and isset( \IPS\Request::i()->stream_custom_members ) )
|
||||
{
|
||||
$members = NULL;
|
||||
foreach( explode( ',', \IPS\Request::i()->stream_custom_members ) as $name )
|
||||
{
|
||||
try
|
||||
{
|
||||
$members[] = \IPS\Member::load( $name, 'name' );
|
||||
}
|
||||
catch( \OutOfRangeException $e ) { }
|
||||
}
|
||||
|
||||
$_values['stream_custom_members'] = $members;
|
||||
}
|
||||
else if ( in_array( $field, $streamFields ) && ( $field == 'classes' || $field == 'followed_types' ) && is_array( \IPS\Request::i()->{ 'stream_' . $field } ) )
|
||||
{
|
||||
/* Some array values will come in as key=1 params, so we only need the keys here */
|
||||
$_values[ $requestKey ] = array_keys( $requestField );
|
||||
}
|
||||
else
|
||||
{
|
||||
$_values[ $requestKey ] = $requestField;
|
||||
}
|
||||
}
|
||||
|
||||
$formattedValues = $stream->formatFormValues( $_values );
|
||||
|
||||
/* Overwrite stream config if present in the request */
|
||||
foreach ( $streamFields as $k )
|
||||
{
|
||||
$requestKey = 'stream_' . $k;
|
||||
|
||||
if ( isset( \IPS\Request::i()->$requestKey ) )
|
||||
{
|
||||
if ( $stream->$k != $formattedValues[ $k ] )
|
||||
{
|
||||
$stream->$k = $formattedValues[ $k ];
|
||||
$stream->baseUrl = $stream->baseUrl->setQueryString( 'stream_' . $k, \IPS\Request::i()->$requestKey );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Containers are special */
|
||||
if ( isset( \IPS\Request::i()->stream_containers ) and is_array( \IPS\Request::i()->stream_containers ) )
|
||||
{
|
||||
/* Remove null/'' values as we no longer want to restrict by container for this class if that occurs */
|
||||
$cleanedContainers = array();
|
||||
foreach( \IPS\Request::i()->stream_containers as $class => $containers )
|
||||
{
|
||||
if ( $containers )
|
||||
{
|
||||
$cleanedContainers[ $class ] = $containers;
|
||||
}
|
||||
}
|
||||
|
||||
if ( count( array_diff_assoc( $cleanedContainers, $stream::containersToUrl( $stream->containers ) ) ) )
|
||||
{
|
||||
$stream->containers = $stream::containersFromUrl( $cleanedContainers );
|
||||
$stream->baseUrl = $stream->baseUrl->setQueryString( 'stream_containers', $cleanedContainers );
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( \IPS\Request::i()->id ) )
|
||||
{
|
||||
/* reset the form to account for all the modifications to $stream class variables */
|
||||
$form = $this->_buildForm( $stream );
|
||||
}
|
||||
}
|
||||
|
||||
/* In order to make most streams more efficient, if we are looking at newest items first, and we haven't set a custom date, then just look for the last 12 months max */
|
||||
if ( $stream->date_type == 'all' and $stream->sort == 'newest' )
|
||||
{
|
||||
$stream->date_relative_days = 365;
|
||||
$stream->date_type = 'relative';
|
||||
}
|
||||
|
||||
/* Build the query */
|
||||
@@ -203,36 +276,62 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Set page or the before/after date */
|
||||
$currentPage = 1;
|
||||
if ( isset( \IPS\Request::i()->page ) )
|
||||
if ( isset( \IPS\Request::i()->page ) AND intval( \IPS\Request::i()->page ) > 0 )
|
||||
{
|
||||
$currentPage = \IPS\Request::i()->page;
|
||||
$query->setPage( $currentPage );
|
||||
}
|
||||
if ( \IPS\Request::i()->isAjax() and isset( \IPS\Request::i()->before ) )
|
||||
|
||||
$before = isset( \IPS\Request::i()->before ) ? \IPS\Request::i()->before : null;
|
||||
$after = isset( \IPS\Request::i()->after ) ? \IPS\Request::i()->after : null;
|
||||
|
||||
/* If we sort by oldest, then we need to switch these values */
|
||||
if ( $stream->sort == 'oldest' )
|
||||
{
|
||||
$tmp = $after;
|
||||
$after = $before;
|
||||
$before = $tmp;
|
||||
unset( $tmp );
|
||||
}
|
||||
|
||||
if ( isset( \IPS\Request::i()->latest ) )
|
||||
{
|
||||
if ( $stream->id and !$stream->include_comments )
|
||||
{
|
||||
$query->filterByLastUpdatedDate( NULL, \IPS\DateTime::ts( \IPS\Request::i()->before ) );
|
||||
$query->filterByLastUpdatedDate( \IPS\DateTime::ts( \IPS\Request::i()->latest ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
$query->filterByCreateDate( NULL, \IPS\DateTime::ts( \IPS\Request::i()->before ) );
|
||||
$query->filterByCreateDate( \IPS\DateTime::ts( \IPS\Request::i()->latest ) );
|
||||
}
|
||||
|
||||
$query->setLimit(350);
|
||||
}
|
||||
if ( \IPS\Request::i()->isAjax() and isset( \IPS\Request::i()->after ) )
|
||||
else if ( $before )
|
||||
{
|
||||
if ( $stream->id and !$stream->include_comments )
|
||||
{
|
||||
$query->filterByLastUpdatedDate( \IPS\DateTime::ts( \IPS\Request::i()->after ) );
|
||||
$query->filterByLastUpdatedDate( NULL, \IPS\DateTime::ts( $before ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
$query->filterByCreateDate( \IPS\DateTime::ts( \IPS\Request::i()->after ) );
|
||||
$query->filterByCreateDate( NULL, \IPS\DateTime::ts( $before ) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $after )
|
||||
{
|
||||
if ( $stream->id and !$stream->include_comments )
|
||||
{
|
||||
$query->filterByLastUpdatedDate( \IPS\DateTime::ts( $after ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
$query->filterByCreateDate( \IPS\DateTime::ts( $after ) );
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the results */
|
||||
$results = $query->search( NULL, $stream->tags ? explode( ',', $stream->tags ) : NULL );
|
||||
$results = $query->search( NULL, $stream->tags ? explode( ',', $stream->tags ) : NULL, ( $stream->include_comments ? \IPS\Content\Search\Query::TAGS_MATCH_ITEMS_ONLY + \IPS\Content\Search\Query::TERM_OR_TAGS : \IPS\Content\Search\Query::TERM_OR_TAGS ) );
|
||||
|
||||
/* Load data we need like the authors, etc */
|
||||
$results->init();
|
||||
@@ -260,44 +359,45 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
$view = 'expanded';
|
||||
$streamID = ( \IPS\Request::i()->id ) ? \IPS\Request::i()->id : 'all';
|
||||
|
||||
if ( ( isset( \IPS\Request::i()->cookie['stream_view_' . $streamID] ) and \IPS\Request::i()->cookie['stream_view_' . $streamID] == 'condensed' ) or ( isset( \IPS\Request::i()->view ) and \IPS\Request::i()->view == 'condensed' ) )
|
||||
if ( isset( \IPS\Request::i()->cookie['stream_view_' . $streamID] ) )
|
||||
{
|
||||
$view = 'condensed';
|
||||
$view = \IPS\Request::i()->cookie['stream_view_' . $streamID];
|
||||
}
|
||||
else
|
||||
{
|
||||
$view = $stream->default_view;
|
||||
}
|
||||
|
||||
|
||||
/* If this is an AJAX request, just show the results */
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
if( isset( \IPS\Request::i()->_changeView ) )
|
||||
{
|
||||
$output = \IPS\Theme::i()->getTemplate('streams')->stream( $stream, $results, !isset( \IPS\Request::i()->id ), true, $baseUrl, ( $stream->id and !$stream->include_comments ) ? 'last_comment' : 'date', $view );
|
||||
}
|
||||
else
|
||||
{
|
||||
$output = \IPS\Theme::i()->getTemplate('streams')->streamItems( $results, true, ( $stream->id and !$stream->include_comments ) ? 'last_comment' : 'date', $view );
|
||||
}
|
||||
$output = \IPS\Theme::i()->getTemplate('streams')->streamItems( $results, TRUE, ( $stream->id and !$stream->include_comments ) ? 'last_comment' : 'date', $view );
|
||||
|
||||
$return = array(
|
||||
'title' => $stream->_title,
|
||||
'title' => htmlspecialchars( $stream->_title, \IPS\HTMLENTITIES | ENT_QUOTES, 'UTF-8', FALSE ),
|
||||
'blurb' => $stream->blurb(),
|
||||
'config' => json_encode( $stream->config() ),
|
||||
'count' => count( $results ),
|
||||
'results' => $output,
|
||||
'id' => ( $stream->id ) ? $stream->id : ''
|
||||
'id' => ( $stream->id ) ? $stream->id : '',
|
||||
'url' => $stream->url()
|
||||
);
|
||||
|
||||
\IPS\Output::i()->json( $return );
|
||||
\IPS\Output::i()->json( $return );
|
||||
return;
|
||||
}
|
||||
|
||||
/* Display - RSS */
|
||||
if ( isset( \IPS\Request::i()->rss ) )
|
||||
if ( \IPS\Settings::i()->activity_stream_rss and isset( \IPS\Request::i()->rss ) )
|
||||
{
|
||||
$document = \IPS\Xml\Rss::newDocument( $baseUrl, $stream->_title, sprintf( \IPS\Member::loggedIn()->language()->get( 'stream_rss_title' ), \IPS\Settings::i()->board_name, $stream->_title ) );
|
||||
$document = \IPS\Xml\Rss::newDocument( $stream->baseUrl, $stream->_title, sprintf( \IPS\Member::loggedIn()->language()->get( 'stream_rss_title' ), \IPS\Settings::i()->board_name, $stream->_title ) );
|
||||
|
||||
foreach ( $results as $result )
|
||||
{
|
||||
$result->addToRssFeed( $document );
|
||||
if ( $result instanceof \IPS\Content\Search\Result\Content )
|
||||
{
|
||||
$result->addToRssFeed( $document );
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->sendOutput( $document->asXML(), 200, 'text/xml' );
|
||||
@@ -309,25 +409,28 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/* What's the RSS Link? */
|
||||
$rssLink = NULL;
|
||||
if ( isset( \IPS\Request::i()->id ) )
|
||||
if ( \IPS\Settings::i()->activity_stream_rss )
|
||||
{
|
||||
$rssLink = \IPS\Http\Url::internal( "app=core&module=discovery&controller=streams&id={$stream->id}", 'front', 'discover_rss' );
|
||||
if ( \IPS\Member::loggedIn()->member_id )
|
||||
if ( isset( \IPS\Request::i()->id ) )
|
||||
{
|
||||
$rssLink = $rssLink->setQueryString( 'member', \IPS\Member::loggedIn()->member_id );
|
||||
if ( !\IPS\Member::loggedIn()->members_pass_salt )
|
||||
$rssLink = \IPS\Http\Url::internal( "app=core&module=discover&controller=streams&id={$stream->id}", 'front', 'discover_rss' );
|
||||
if ( \IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Member::loggedIn()->members_pass_salt = \IPS\Member::loggedIn()->generateSalt();
|
||||
\IPS\Member::loggedIn()->save();
|
||||
$rssLink = $rssLink->setQueryString( 'member', \IPS\Member::loggedIn()->member_id )->setQueryString( 'key', md5( ( \IPS\Member::loggedIn()->members_pass_hash ?: \IPS\Member::loggedIn()->email ) . \IPS\Member::loggedIn()->members_pass_salt ) );
|
||||
}
|
||||
$rssLink = $rssLink->setQueryString( 'key', md5( ( \IPS\Member::loggedIn()->members_pass_hash ?: \IPS\Member::loggedIn()->email ) . \IPS\Member::loggedIn()->members_pass_salt ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It's all activity! */
|
||||
$rssLink = \IPS\Http\Url::internal( "app=core&module=discover&controller=streams", 'front', 'discover_rss_all_activity' );
|
||||
}
|
||||
}
|
||||
|
||||
/* Display */
|
||||
$output = \IPS\Theme::i()->getTemplate('streams')->stream( $stream, $results, !isset( \IPS\Request::i()->id ), true, $baseUrl, ( $stream->id and !$stream->include_comments ) ? 'last_comment' : 'date', $view );
|
||||
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('streams')->streamWrapper( $stream, $output, ( isset( \IPS\Request::i()->id ) and ( !$stream->member or $stream->member == \IPS\Member::loggedIn()->member_id ) ) ? TRUE : FALSE, $rssLink, isset( \IPS\Request::i()->id ) and $stream->member and $stream->member != \IPS\Member::loggedIn()->member_id );
|
||||
$output = \IPS\Theme::i()->getTemplate('streams')->stream( $stream, $results, $stream->id ? FALSE : TRUE, TRUE, ( $stream->id and !$stream->include_comments ) ? 'last_comment' : 'date', $view );
|
||||
|
||||
\IPS\Output::i()->jsVars['stream_config'] = $stream->config();
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('streams')->streamWrapper( $stream, $output, $form, $rssLink, isset( \IPS\Request::i()->id ) and $stream->member and \IPS\Member::loggedIn()->member_id and $stream->member != \IPS\Member::loggedIn()->member_id );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,13 +441,72 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
if ( !\IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission_guest', '2C280/A', 403, '' );
|
||||
}
|
||||
|
||||
$stream = new \IPS\core\Stream;
|
||||
$stream->member = \IPS\Member::loggedIn()->member_id;
|
||||
$stream->default_view = 'expanded';
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'create_new_stream' );
|
||||
\IPS\Output::i()->output = $this->_buildForm( $stream );
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit a stream's title
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
if ( !\IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission_guest', '2C280/6', 403, '' );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$stream = \IPS\core\Stream::load( \IPS\Request::i()->id );
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C280/7', 404, '' );
|
||||
}
|
||||
|
||||
if ( $stream->member != \IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_permission', '2C280/8', 403, '' );
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->class = 'ipsForm_vertical';
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'stream_title', $stream->title ) );
|
||||
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
if ( isset( $values['stream_title'] ) and $values['stream_title'] )
|
||||
{
|
||||
$stream->title = $values['stream_title'];
|
||||
$stream->save();
|
||||
$this->_rebuildStreams();
|
||||
\IPS\Output::i()->redirect( $stream->url() );
|
||||
}
|
||||
}
|
||||
|
||||
/* Output */
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->genericBlock( $form, NULL, 'ipsPad' ), 200, 'text/html', \IPS\Output::i()->httpHeaders );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'stream_edit_title' );
|
||||
\IPS\Output::i()->output = $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a stream
|
||||
*
|
||||
@@ -352,6 +514,13 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
public function copy()
|
||||
{
|
||||
if ( !\IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission_guest', '2C280/4', 403, '' );
|
||||
}
|
||||
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
try
|
||||
{
|
||||
$stream = clone \IPS\core\Stream::load( \IPS\Request::i()->id );
|
||||
@@ -361,7 +530,7 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C280/3', 404, '' );
|
||||
\IPS\Output::i()->error( 'node_error', '2C280/5', 404, '' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( $stream->url() );
|
||||
@@ -374,6 +543,11 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
/* Make sure the user confirmed the deletion */
|
||||
\IPS\Request::i()->confirmedDelete();
|
||||
|
||||
try
|
||||
{
|
||||
$stream = \IPS\core\Stream::load( \IPS\Request::i()->id );
|
||||
@@ -392,17 +566,54 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=discover&controller=streams", 'front', 'discover_all' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the container Node form element HTML
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getContainerNodeElement()
|
||||
{
|
||||
$currentContainers = array();
|
||||
$stream = NULL;
|
||||
if ( isset( \IPS\Request::i()->id ) )
|
||||
{
|
||||
$stream = \IPS\core\Stream::load( \IPS\Request::i()->id );
|
||||
$currentContainers = $stream->containers ? json_decode( $stream->containers, TRUE ) : array();
|
||||
|
||||
if ( isset( \IPS\Request::i()->stream_containers ) )
|
||||
{
|
||||
$currentContainers = json_decode( $stream::containersFromUrl( \IPS\Request::i()->stream_containers ), TRUE );
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( \IPS\Content::routedClasses( TRUE, FALSE, TRUE ) as $class )
|
||||
{
|
||||
$classes[ $class ] = $class::$title . '_pl';
|
||||
if ( isset( $class::$containerNodeClass ) and $class == \IPS\Request::i()->className )
|
||||
{
|
||||
$url = $stream ? $stream->baseUrl->setQueryString( 'className', $class ) : \IPS\Request::i()->url()->setQueryString( 'className', $class );
|
||||
$containerClass = $class::$containerNodeClass;
|
||||
$field = new \IPS\Helpers\Form\Node( 'stream_containers_' . $class::$title, isset( $currentContainers[ $class ] ) ? $currentContainers[ $class ] : array(), NULL, array( 'url' => $url, 'class' => $class::$containerNodeClass, 'multiple' => TRUE, 'permissionCheck' => $containerClass::searchableNodesPermission() ), NULL, NULL, NULL, 'stream_containers_' . $class::$title );
|
||||
$field->label = \IPS\Member::loggedIn()->language()->addToStack( 'stream_narrow_by_container_label', NULL, array( 'sprintf' => array( \IPS\Member::loggedIn()->language()->addToStack( $containerClass::$nodeTitle ) ) ) );
|
||||
|
||||
return \IPS\Output::i()->json( array( 'node' => \IPS\Theme::i()->getTemplate('streams')->filterFormContentTypeContent( $field, $class, \IPS\Request::i()->key ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build form
|
||||
*
|
||||
* @param \IPS\core\Stream $stream The stream
|
||||
* @return string
|
||||
*/
|
||||
protected function _buildForm( \IPS\core\Stream $stream )
|
||||
protected function _buildForm( \IPS\core\Stream &$stream )
|
||||
{
|
||||
/* Build form */
|
||||
$form = new \IPS\Helpers\Form( 'select_blog', 'continue', ( $stream->id ? $stream->url() : NULL ) );
|
||||
$form = new \IPS\Helpers\Form( 'stream', 'continue', ( $stream->id ? $stream->url() : NULL ) );
|
||||
$form->class = 'ipsForm_vertical ipsForm_noLabels';
|
||||
|
||||
$stream->form( $form, 'Text', !$stream->id );
|
||||
@@ -413,44 +624,62 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$form->hiddenValues['__custom_stream'] = TRUE;
|
||||
}
|
||||
|
||||
|
||||
if ( $stream->member )
|
||||
{
|
||||
$form->hiddenValues['__stream_owner'] = $stream->member;
|
||||
}
|
||||
|
||||
$form->hiddenValues['stream_default_view'] = $stream->default_view;
|
||||
|
||||
/* Handle submissions */
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
/* Update only */
|
||||
if ( !$stream->member or isset( \IPS\Request::i()->updateOnly ) )
|
||||
{
|
||||
/* As the node container form elements are not in the actual form, we need to work some magic. And by magic, I do mean a sort of hacky thing. */
|
||||
foreach ( \IPS\Request::i() as $k => $v )
|
||||
{
|
||||
$url = $stream->url();
|
||||
$formattedValues = $stream->formatFormValues( $values );
|
||||
|
||||
foreach ( array( 'include_comments', 'classes', 'containers', 'ownership', 'read', 'follow', 'date_type', 'date_start', 'date_end', 'date_relative_days' ) as $k )
|
||||
if ( mb_substr( $k, 0, 18 ) == 'stream_containers_' and $v )
|
||||
{
|
||||
if ( $stream->$k != $formattedValues[ $k ] )
|
||||
$vals = explode( ',', $v );
|
||||
$values[ $k ] = array_combine( $vals, $vals );
|
||||
}
|
||||
}
|
||||
|
||||
/* Update only */
|
||||
if ( isset( \IPS\Request::i()->updateOnly ) )
|
||||
{
|
||||
$formattedValues = $stream->formatFormValues( $values );
|
||||
|
||||
foreach ( array( 'include_comments', 'classes', 'containers', 'ownership', 'custom_members', 'read', 'follow', 'followed_types', 'date_type', 'date_start', 'date_end', 'date_relative_days', 'sort', 'tags', 'unread_links' ) as $k )
|
||||
{
|
||||
$requestKey = 'stream_' . $k;
|
||||
if ( isset( $formattedValues[ $k ] ) AND $stream->$k != $formattedValues[ $k ] )
|
||||
{
|
||||
$url = $url->setQueryString( $k, $formattedValues[ $k ] );
|
||||
$stream->$k = $formattedValues[ $k ];
|
||||
$stream->baseUrl = $stream->baseUrl->setQueryString( 'stream_' . $k, \IPS\Request::i()->$requestKey );
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( $url );
|
||||
}
|
||||
/* Update & Save */
|
||||
else
|
||||
{
|
||||
{
|
||||
if ( !$stream->id )
|
||||
{
|
||||
$stream->position = \IPS\Db::i()->select( 'MAX(position)', 'core_streams', array( 'member=?', \IPS\Member::loggedIn()->member_id ) )->first() + 1;
|
||||
$redirectAfterSave = TRUE;
|
||||
}
|
||||
|
||||
if ( count( $values['stream_classes'] ) )
|
||||
else
|
||||
{
|
||||
$values['stream_classes_type'] = 1;
|
||||
if ( !$stream->member or $stream->member != \IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C280/9', 403, '' );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$stream->saveForm( $stream->formatFormValues( $values ) );
|
||||
|
||||
$this->_rebuildStreams();
|
||||
|
||||
|
||||
if( $redirectAfterSave )
|
||||
{
|
||||
\IPS\Output::i()->redirect( $stream->url() );
|
||||
@@ -459,7 +688,7 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/* Display */
|
||||
return $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'streams', 'core' ) ), $stream->id ? ( $stream->member ? 'filterUpdateForm' : 'filterDuplicateForm' ) : 'filterCreateForm' ) );
|
||||
return $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'streams', 'core' ) ), $stream->id ? 'filterInlineForm' : 'filterCreateForm' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -470,7 +699,7 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
protected function _rebuildStreams()
|
||||
{
|
||||
$default = \IPS\Member::loggedIn()->defaultStream;
|
||||
\IPS\Member::loggedIn()->member_streams = json_encode( array( 'default' => $default, 'streams' => iterator_to_array( \IPS\Db::i()->select( 'id, title', 'core_streams', array( 'member=?', \IPS\Member::loggedIn()->member_id ) )->setKeyField('id')->setValueField('title') ) ) );
|
||||
\IPS\Member::loggedIn()->member_streams = json_encode( array( 'default' => $default, 'streams' => iterator_to_array( \IPS\Db::i()->select( 'id, title', 'core_streams', array( 'member=?', \IPS\Member::loggedIn()->member_id ), NULL, NULL, NULL, NULL, \IPS\Db::SELECT_FROM_WRITE_SERVER )->setKeyField('id')->setValueField('title') ) ) );
|
||||
\IPS\Member::loggedIn()->save();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user