Version 4.1.19
This commit is contained in:
1 parent
28bd025b35
commit
2bd5025018
2674 files changed
+233518
-77766
No files matched your search
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Contact Form
|
||||
* @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 12 Nov 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -23,7 +23,21 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
*/
|
||||
class _contact extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
if ( !static::canUseContactUs() )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_permission', '2S333/1', 403, '' );
|
||||
}
|
||||
|
||||
/* Execute */
|
||||
return parent::execute();
|
||||
}
|
||||
/**
|
||||
* Method
|
||||
*
|
||||
@@ -31,6 +45,10 @@ class _contact extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function manage()
|
||||
{
|
||||
/* Get extensions */
|
||||
$extensions = \IPS\Application::allExtensions( 'core', 'ContactUs', FALSE, 'core', 'InternalEmail', TRUE );
|
||||
|
||||
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
|
||||
@@ -41,39 +59,87 @@ class _contact extends \IPS\Dispatcher\Controller
|
||||
'app' => 'core',
|
||||
'key' => 'Contact',
|
||||
'autoSaveKey' => 'contact-' . \IPS\Member::loggedIn()->member_id,
|
||||
//'minimize' => 'x',
|
||||
) ) );
|
||||
|
||||
if ( !\IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'contact_name', NULL, TRUE ) );
|
||||
$form->add( new \IPS\Helpers\Form\Email( 'email_address', NULL, TRUE ) );
|
||||
$form->add( new \IPS\Helpers\Form\Captcha );
|
||||
$form->add( new \IPS\Helpers\Form\Email( 'email_address', NULL, TRUE, array( 'bypassProfanity' => TRUE ) ) );
|
||||
if ( \IPS\Settings::i()->bot_antispam_type !== 'none' and \IPS\Settings::i()->guest_captcha )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Captcha );
|
||||
}
|
||||
}
|
||||
foreach ( $extensions as $k => $class )
|
||||
{
|
||||
$class->runBeforeFormOutput( $form );
|
||||
}
|
||||
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
/* Send the message */
|
||||
$fromName = ( \IPS\Member::loggedIn()->member_id ) ? \IPS\Member::loggedIn()->name : $values['contact_name'];
|
||||
$mail = \IPS\Email::buildFromTemplate( 'core', 'contact_form', array( \IPS\Member::loggedIn(), $fromName, $values['contact_text'] ) );
|
||||
foreach ( $extensions as $k => $class )
|
||||
{
|
||||
if ( $handled = $class->handleForm( $values ) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set contact email as Reply-To instead of From, so that it will pass Spam/SPF checks */
|
||||
$mail->headers['Reply-To'] = '=?UTF-8?B?' . base64_encode( $fromName ) . "?= <" . ( \IPS\Member::loggedIn()->member_id ? \IPS\Member::loggedIn()->email : $values['email_address'] ) . '>';
|
||||
$mail->send( \IPS\Settings::i()->email_in );
|
||||
|
||||
if( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->json( 'OK' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('message_sent');
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'message_sent' );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->contactDone();
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('contact');
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'contact' );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->contact( $form );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the current user allowed to use the contact us form
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function canUseContactUs()
|
||||
{
|
||||
try
|
||||
{
|
||||
$module = \IPS\Application\Module::get( 'core', 'contact' );
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ( !\IPS\Member::loggedIn()->canAccessModule( $module ) )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* If all groups have access, we can */
|
||||
if( \IPS\Settings::i()->contact_access != '*' )
|
||||
{
|
||||
/* Check member */
|
||||
$member = \IPS\Member::loggedIn();
|
||||
$memberGroups = array_merge( array( $member->member_group_id ), array_filter( explode( ',', $member->mgroup_others ) ) );
|
||||
$accessGroups = explode( ',', \IPS\Settings::i()->contact_access );
|
||||
|
||||
/* Are we in an allowed group? */
|
||||
if( count( array_intersect( $accessGroups, $memberGroups ) ) )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Profile
|
||||
* @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 19 Jul 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -23,7 +23,6 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
*/
|
||||
class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* [Content\Controller] Class
|
||||
*/
|
||||
@@ -54,6 +53,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_statuses.js', 'core' ) );
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/profiles.css' ) );
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/streams.css' ) );
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/leaderboard.css' ) );
|
||||
|
||||
if ( \IPS\Theme::i()->settings['responsive'] )
|
||||
{
|
||||
@@ -104,7 +104,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
$canAccessStatuses = $canAccessSingleStatuses and ( $this->member->pp_setting_count_comments or \IPS\Member::loggedIn()->member_id == $this->member->member_id );
|
||||
|
||||
/* Are we loading a different page of comments? */
|
||||
if ( \IPS\Request::i()->status && \IPS\Request::i()->isAjax() && !\IPS\Request::i()->submitting && !\IPS\Request::i()->getUploader && $canAccessStatuses )
|
||||
if ( \IPS\Request::i()->status && \IPS\Request::i()->isAjax() && \IPS\Request::i()->page && $canAccessStatuses )
|
||||
{
|
||||
$status = \IPS\core\Statuses\Status::loadAndCheckPerms( \IPS\Request::i()->status );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'statuses' )->statusReplies( $status );
|
||||
@@ -152,10 +152,18 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
/* Work out the main content to display */
|
||||
if ( $canAccessSingleStatuses and \IPS\Request::i()->status and \IPS\Request::i()->type == 'status' )
|
||||
{
|
||||
$status = \IPS\core\Statuses\Status::loadAndCheckPerms( \IPS\Request::i()->status );
|
||||
try
|
||||
{
|
||||
$status = \IPS\core\Statuses\Status::loadAndCheckPerms( \IPS\Request::i()->status );
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C138/E', 404, '' );
|
||||
}
|
||||
|
||||
$mainContent = \IPS\Theme::i()->getTemplate( 'profile' )->singleStatus( $this->member, $status );
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->get( 'viewing_single_status' );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'viewing_single_status_of', FALSE, array('sprintf' => array( \IPS\DateTime::ts( $status->mapped('date') )->localeDate() , $status->author()->name ) ) );
|
||||
\IPS\Output::i()->breadcrumb[] = array( NULL, \IPS\Member::loggedIn()->language()->get( 'viewing_single_status' ) );
|
||||
}
|
||||
else
|
||||
@@ -257,7 +265,16 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
elseif ( mb_substr( $tab, 0, 6 ) == 'field_' )
|
||||
{
|
||||
$fieldId = mb_substr( $tab, 6 );
|
||||
$tabContents = \IPS\Theme::i()->getTemplate( 'profile' )->fieldTab( $fieldId, $fields[ $fieldId ] );
|
||||
foreach( $mainFields as $group => $fields )
|
||||
{
|
||||
foreach( $fields as $field => $value )
|
||||
{
|
||||
if ( $field == $fieldId )
|
||||
{
|
||||
$tabContents = \IPS\Theme::i()->getTemplate( 'profile' )->fieldTab( $fieldId, $value );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif ( mb_substr( $tab, 0, 5 ) == 'node_' )
|
||||
{
|
||||
@@ -298,12 +315,17 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
$visitorInfo = json_decode( $this->member->pp_last_visitors, TRUE );
|
||||
if ( is_array( $visitorInfo ) and $this->member->members_bitoptions['pp_setting_count_visitors'] )
|
||||
{
|
||||
$visitorData = array();
|
||||
foreach( new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'core_members', array( \IPS\Db::i()->in( 'member_id', array_keys( array_reverse( $visitorInfo, TRUE ) ) ) ) ), 'IPS\Member' ) AS $row )
|
||||
{
|
||||
$visitorData[$row->member_id] = $row;
|
||||
}
|
||||
|
||||
foreach( array_reverse( $visitorInfo, TRUE ) as $id => $time )
|
||||
{
|
||||
$visitor = \IPS\Member::load( $id );
|
||||
if ( $visitor->member_id )
|
||||
if ( isset( $visitorData[$id] ) )
|
||||
{
|
||||
$visitors[$id]['member'] = $visitor;
|
||||
$visitors[$id]['member'] = $visitorData[$id];
|
||||
$visitors[$id]['visit_time'] = $time;
|
||||
}
|
||||
}
|
||||
@@ -425,6 +447,16 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
{
|
||||
$query = \IPS\Content\Search\Query::init()->filterByAuthor( $this->member )->setOrder( \IPS\Content\Search\Query::ORDER_NEWEST_UPDATED )->setPage( $page );
|
||||
$results = $query->search();
|
||||
|
||||
/* If we requested a higher page than is allowed, redirect back to last page */
|
||||
$totalResults = $results->count( TRUE );
|
||||
|
||||
if( $totalResults AND ceil( $totalResults / $query->resultsToGet ) < $page )
|
||||
{
|
||||
$highestPage = floor( $totalResults / $query->resultsToGet );
|
||||
\IPS\Output::i()->redirect( \IPS\Request::i()->url()->setQueryString( 'page', $highestPage ?: 1 ), NULL, 303 );
|
||||
}
|
||||
|
||||
$pagination = trim( \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $this->member->url()->setQueryString( array( 'do' => 'content' ) ), ceil( $results->count( TRUE ) / $query->resultsToGet ), $page, $query->resultsToGet ) );
|
||||
$output = \IPS\Theme::i()->getTemplate('profile')->userContentStream( $this->member, $results, $pagination );
|
||||
}
|
||||
@@ -435,7 +467,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
$currentApp = $currentAppArray[0];
|
||||
if( isset( $hasCallback[ $currentType ] ) )
|
||||
{
|
||||
$output = $hasCallback[ $currentType ]->customTableHelper( $currentClass, $this->member->url()->setQueryString( array( 'do' => 'content', 'type' => $currentType ) ), array( array( $currentClass::$databaseTable . '.' . $currentClass::$databasePrefix . $currentClass::$databaseColumnMap['author'] . '=?', $this->member->member_id ) ) );
|
||||
$output = $hasCallback[ $currentType ]->customTableHelper( $currentClass, \IPS\Http\Url::internal( "app=core&module=members&controller=profile&id={$this->member->member_id}&do=content", 'front', 'profile_content', $this->member->members_seo_name )->setQueryString( array( 'type' => $currentType ) ), array( array( $currentClass::$databaseTable . '.' . $currentClass::$databasePrefix . $currentClass::$databaseColumnMap['author'] . '=?', $this->member->member_id ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -445,21 +477,25 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
{
|
||||
$where[] = array( $currentClass::$databaseTable . '.' . $currentClass::$databasePrefix . $currentClass::$databaseColumnMap['state'] . ' != ?', 'link' );
|
||||
}
|
||||
|
||||
|
||||
if ( isset( $currentClass::$databaseColumnMap['status'] ) )
|
||||
{
|
||||
$where[] = array( $currentClass::$databaseTable . '.' . $currentClass::$databasePrefix . $currentClass::$databaseColumnMap['status'] . ' != ?', 'draft' );
|
||||
}
|
||||
|
||||
if( method_exists( $currentClass, 'commentWhere' ) AND $currentClass::commentWhere() !== NULL )
|
||||
{
|
||||
$where[] = $currentClass::commentWhere();
|
||||
}
|
||||
|
||||
$output = new \IPS\Helpers\Table\Content( $currentClass, $this->member->url()->setQueryString( array( 'do' => 'content', 'type' => $currentType ) ), $where, NULL, NULL, 'read', FALSE );
|
||||
$output = new \IPS\Helpers\Table\Content( $currentClass, \IPS\Http\Url::internal( "app=core&module=members&controller=profile&id={$this->member->member_id}&do=content", 'front', 'profile_content', $this->member->members_seo_name )->setQueryString( array( 'type' => $currentType ) ), $where, NULL, NULL, 'read', FALSE );
|
||||
}
|
||||
|
||||
if ( $currentType == 'core_statuses_status' )
|
||||
{
|
||||
$output->noModerate = TRUE;
|
||||
}
|
||||
|
||||
$output->showFilters = FALSE;
|
||||
|
||||
$output->classes[] = 'cProfileContent';
|
||||
}
|
||||
|
||||
@@ -471,7 +507,8 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
else
|
||||
{
|
||||
/* Display */
|
||||
\IPS\Output::i()->title = $this->member->name;
|
||||
$title = ( isset( \IPS\Request::i()->page ) and \IPS\Request::i()->page > 1 ) ? \IPS\Member::loggedIn()->language()->addToStack( 'title_with_page_number', FALSE, array( 'sprintf' => array( $this->member->name, \IPS\Request::i()->page ) ) ) : $this->member->name;
|
||||
\IPS\Output::i()->title = $title;
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/statuses.css' ) );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'profile' )->userContent( $this->member, $types, $currentAppModule, $currentType, (string) $output );
|
||||
}
|
||||
@@ -545,105 +582,23 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
|
||||
/* Build Output */
|
||||
$url = \IPS\Http\Url::internal( "app=core&module=members&controller=profile&id={$this->member->member_id}&do=reputation&type={$currentType}", 'front', 'profile_reputation', array( $this->member->members_seo_name ) );
|
||||
$where = array( array( '( core_reputation_index.member_id=? OR core_reputation_index.member_received=? ) AND core_reputation_index.app=? AND core_reputation_index.type=?', $this->member->member_id, $this->member->member_id, $currentClass::$application, $currentClass::$reputationType ) );
|
||||
|
||||
if( method_exists( $currentClass, 'commentWhere' ) AND $currentClass::commentWhere() !== NULL )
|
||||
{
|
||||
$where[] = $currentClass::commentWhere();
|
||||
}
|
||||
|
||||
$containerClass = NULL;
|
||||
$permClass = $currentClass;
|
||||
|
||||
if ( isset( $currentClass::$itemClass ) )
|
||||
{
|
||||
$permClass = $currentClass::$itemClass;
|
||||
}
|
||||
|
||||
if ( in_array( 'IPS\Content\Permissions', class_implements( $permClass ) ) )
|
||||
{
|
||||
$containerClass = $permClass::$containerNodeClass;
|
||||
$permissionKey = 'read';
|
||||
$member = \IPS\Member::loggedIn();
|
||||
$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[ $permissionKey ], $member->groups ) . ' OR ' . 'perm_' . $containerClass::$permissionMap[ $permissionKey ] . "='*' )" ) ) as $result )
|
||||
{
|
||||
$categories[] = $result;
|
||||
}
|
||||
|
||||
if( count( $categories ) )
|
||||
{
|
||||
$where[] = array( $permClass::$databaseTable . "." . $permClass::$databasePrefix . $permClass::$databaseColumnMap['container'] . ' IN(' . implode( ',', $categories ) . ')' );
|
||||
}
|
||||
else
|
||||
{
|
||||
$where[] = array( $permClass::$databaseTable . "." . $permClass::$databasePrefix . $permClass::$databaseColumnMap['container'] . '=0' );
|
||||
}
|
||||
}
|
||||
|
||||
$table = new \IPS\Helpers\Table\Db( $currentClass::$databaseTable, $url, $where );
|
||||
$table = new \IPS\Helpers\Table\Content( $currentClass, $url, NULL, NULL, \IPS\Content\Hideable::FILTER_AUTOMATIC, 'read', FALSE );
|
||||
$table->joinContainer = TRUE;
|
||||
$table->sortOptions = array( 'rep_date' );
|
||||
$table->sortBy = 'rep_date';
|
||||
$table->joins = array(
|
||||
array( 'select' => "core_reputation_index.id AS rep_id, core_reputation_index.rep_date, core_reputation_index.rep_rating, core_reputation_index.member_received as rep_member_received, core_reputation_index.member_id as rep_member", 'from' => 'core_reputation_index', 'where' => array( "core_reputation_index.type_id=" . $currentClass::$databaseTable . "." . $currentClass::$databasePrefix . $currentClass::$databaseColumnId ) ),
|
||||
array(
|
||||
'select' => "core_reputation_index.id AS rep_id, core_reputation_index.rep_date, core_reputation_index.rep_rating, core_reputation_index.member_received as rep_member_received, core_reputation_index.member_id as rep_member",
|
||||
'from' => 'core_reputation_index',
|
||||
'where' => array( "core_reputation_index.type_id=" . $currentClass::$databaseTable . "." . $currentClass::$databasePrefix . $currentClass::$databaseColumnId . " AND ( core_reputation_index.member_id=? OR core_reputation_index.member_received=? ) AND core_reputation_index.app=? AND core_reputation_index.type=?", $this->member->member_id, $this->member->member_id, $currentClass::$application, $currentClass::$reputationType ),
|
||||
'type' => 'INNER'
|
||||
)
|
||||
);
|
||||
|
||||
if ( $containerClass )
|
||||
{
|
||||
if ( isset( $currentClass::$itemClass ) )
|
||||
{
|
||||
$itemClass = $currentClass::$itemClass;
|
||||
|
||||
$table->joins[] = array(
|
||||
'select' => $itemClass::$databaseTable . '.*',
|
||||
'from' => $itemClass::$databaseTable,
|
||||
'where' => array( $currentClass::$databaseTable . '.' . $currentClass::$databasePrefix . $currentClass::$databaseColumnMap['item'] . '=' . $itemClass::$databaseTable . '.' . $itemClass::$databasePrefix . $itemClass::$databaseColumnId )
|
||||
);
|
||||
}
|
||||
|
||||
$table->joins[] = array(
|
||||
'select' => $containerClass::$databaseTable . '.*',
|
||||
'from' => $containerClass::$databaseTable,
|
||||
'where' => array( $permClass::$databaseTable . '.' . $permClass::$databasePrefix . $permClass::$databaseColumnMap['container'] . '=' . $containerClass::$databaseTable . '.' . $containerClass::$databasePrefix . $containerClass::$databaseColumnId )
|
||||
);
|
||||
}
|
||||
|
||||
$table->tableTemplate = array( \IPS\Theme::i()->getTemplate( 'profile', 'core' ), 'userReputationTable' );
|
||||
$table->rowsTemplate = array( \IPS\Theme::i()->getTemplate( 'profile', 'core' ), 'userReputationRows' );
|
||||
$table->showAdvancedSearch = FALSE;
|
||||
$table->include = array( 'obj', 'reputationData' );
|
||||
$table->parsers = array(
|
||||
'obj' => function( $val, $row ) use ( $currentClass )
|
||||
{
|
||||
try
|
||||
{
|
||||
$return = $currentClass::constructFromData( $row );
|
||||
if ( $return instanceof \IPS\Content\Comment )
|
||||
{
|
||||
$return->item(); // Prevent the exception later
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
if ( $row['rep_id'] )
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_reputation_index', array( 'id=?', $row['rep_id'] ) );
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
'reputationData' => function( $val, $row )
|
||||
{
|
||||
return array(
|
||||
'rep_date' => $row['rep_date'],
|
||||
'rep_rating' => $row['rep_rating'],
|
||||
'rep_member' => $row['rep_member'],
|
||||
'rep_member_received' => $row['rep_member_received'],
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
/* Display */
|
||||
if ( \IPS\Request::i()->isAjax() && \IPS\Request::i()->change_section )
|
||||
@@ -651,8 +606,9 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
\IPS\Output::i()->sendOutput( (string) $table );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->title = $this->member->name;
|
||||
{
|
||||
\IPS\Output::i()->title = ( $table->page > 1 ) ? \IPS\Member::loggedIn()->language()->addToStack( 'title_with_page_number', FALSE, array( 'sprintf' => array( \IPS\Member::loggedIn()->language()->addToStack( 'member_reputation_from', FALSE, array('sprintf' => $this->member->name ) ), $table->page ) ) ) : \IPS\Member::loggedIn()->language()->addToStack( 'member_reputation_from', FALSE, array('sprintf' => $this->member->name ) );
|
||||
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'profile' )->userReputation( $this->member, $types, $currentAppModule, $currentType, (string) $table );
|
||||
}
|
||||
}
|
||||
@@ -760,175 +716,12 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
\IPS\Output::i()->error( 'no_permission_edit_profile', '2S147/1', 403, '' );
|
||||
}
|
||||
|
||||
/* Build the form */
|
||||
$form = new \IPS\Helpers\Form;
|
||||
|
||||
/* The basics */
|
||||
$form->addTab( 'profile_edit_basic_tab', 'user');
|
||||
$form->addHeader( 'profile_edit_basic_header' );
|
||||
if( \IPS\Settings::i()->post_titlechange != -1 and ( isset( \IPS\Settings::i()->post_titlechange ) and $this->member->member_posts >= \IPS\Settings::i()->post_titlechange ) )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'member_title', $this->member->member_title, FALSE, array( 'maxLength' => 64 ) ) );
|
||||
}
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Custom( 'bday', array( 'year' => $this->member->bday_year, 'month' => $this->member->bday_month, 'day' => $this->member->bday_day ), FALSE, array( 'getHtml' => function( $element )
|
||||
{
|
||||
return strtr( \IPS\Member::loggedIn()->language()->preferredDateFormat(), array(
|
||||
'dd' => \IPS\Theme::i()->getTemplate( 'members', 'core', 'global' )->bdayForm_day( $element->name, $element->value, $element->error ),
|
||||
'mm' => \IPS\Theme::i()->getTemplate( 'members', 'core', 'global' )->bdayForm_month( $element->name, $element->value, $element->error ),
|
||||
'yy' => \IPS\Theme::i()->getTemplate( 'members', 'core', 'global' )->bdayForm_year( $element->name, $element->value, $element->error ),
|
||||
'yyyy' => \IPS\Theme::i()->getTemplate( 'members', 'core', 'global' )->bdayForm_year( $element->name, $element->value, $element->error ),
|
||||
) );
|
||||
} ) ) );
|
||||
if ( \IPS\Settings::i()->profile_comments and $this->member->canAccessModule( \IPS\Application\Module::get( 'core', 'status' ) ) )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'enable_status_updates', $this->member->pp_setting_count_comments ) );
|
||||
}
|
||||
|
||||
/* Profile fields */
|
||||
try
|
||||
{
|
||||
$values = \IPS\Db::i()->select( '*', 'core_pfields_content', array( 'member_id=?', $this->member->member_id ) )->first();
|
||||
}
|
||||
catch( \UnderflowException $e )
|
||||
{
|
||||
$values = array();
|
||||
}
|
||||
|
||||
foreach ( \IPS\core\ProfileFields\Field::fields( $values, \IPS\core\ProfileFields\PROFILE ) as $group => $fields )
|
||||
{
|
||||
$form->addHeader( "core_pfieldgroups_{$group}" );
|
||||
foreach ( $fields as $field )
|
||||
{
|
||||
$form->add( $field );
|
||||
}
|
||||
}
|
||||
|
||||
/* Moderator stuff */
|
||||
if ( \IPS\Member::loggedIn()->modPermission('can_modify_profiles') AND \IPS\Member::loggedIn()->member_id != $this->member->member_id )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Editor( 'signature', $this->member->signature, FALSE, array( 'app' => 'core', 'key' => 'Signatures', 'autoSaveKey' => "frontsig-" . $this->member->member_id, 'attachIds' => array( $this->member->member_id ) ) ) );
|
||||
|
||||
$form->addTab( 'profile_edit_moderation', 'times' );
|
||||
|
||||
if ( $this->member->mod_posts !== 0 )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'remove_mod_posts', NULL, FALSE ) );
|
||||
}
|
||||
|
||||
if ( $this->member->restrict_post !== 0 )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'remove_restrict_post', NULL, FALSE ) );
|
||||
}
|
||||
|
||||
if ( $this->member->temp_ban !== 0 )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'remove_ban', NULL, FALSE ) );
|
||||
}
|
||||
}
|
||||
$form = $this->buildEditForm();
|
||||
|
||||
/* Handle the submission */
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
if( ( \IPS\Settings::i()->post_titlechange == -1 or ( isset( \IPS\Settings::i()->post_titlechange ) and $this->member->member_posts >= \IPS\Settings::i()->post_titlechange ) ) AND isset( $values['member_title'] ) )
|
||||
{
|
||||
$this->member->member_title = $values['member_title'];
|
||||
}
|
||||
|
||||
if( $values['bday'] and ( ( $values['bday']['day'] and !$values['bday']['month'] ) or ( $values['bday']['month'] and !$values['bday']['day'] ) ) )
|
||||
{
|
||||
$form->error = \IPS\Member::loggedIn()->language()->addToStack( 'bday_month_and_day_required' );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'forms', 'core' )->editContentForm( \IPS\Member::loggedIn()->language()->addToStack( 'profile_edit' ), $form );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( $values['bday'] and $values['bday']['day'] and $values['bday']['month'] )
|
||||
{
|
||||
$this->member->bday_day = $values['bday']['day'];
|
||||
$this->member->bday_month = $values['bday']['month'];
|
||||
$this->member->bday_year = $values['bday']['year'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->member->bday_day = NULL;
|
||||
$this->member->bday_month = NULL;
|
||||
$this->member->bday_year = NULL;
|
||||
}
|
||||
|
||||
if ( isset( $values['enable_status_updates'] ) )
|
||||
{
|
||||
$this->member->pp_setting_count_comments = $values['enable_status_updates'];
|
||||
|
||||
if ( $values['enable_status_updates'] )
|
||||
{
|
||||
\IPS\Content\Search\Index::i()->massUpdate( 'IPS\core\Statuses\Status', NULL, NULL, '*', NULL, NULL, $this->member->member_id );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Content\Search\Index::i()->massUpdate( 'IPS\core\Statuses\Status', NULL, NULL, '', NULL, NULL, $this->member->member_id );
|
||||
}
|
||||
}
|
||||
|
||||
/* Profile Fields */
|
||||
try
|
||||
{
|
||||
$profileFields = \IPS\Db::i()->select( '*', 'core_pfields_content', array( 'member_id=?', $this->member->member_id ) )->first();
|
||||
}
|
||||
catch( \UnderflowException $e )
|
||||
{
|
||||
$profileFields = array();
|
||||
}
|
||||
|
||||
/* If the row only contains one column (eg. member_id) then the result of the query is a string, we do not want this */
|
||||
if ( !is_array( $profileFields ) )
|
||||
{
|
||||
$profileFields = array();
|
||||
}
|
||||
|
||||
$profileFields['member_id'] = $this->member->member_id;
|
||||
|
||||
foreach ( \IPS\core\ProfileFields\Field::fields( $profileFields, \IPS\core\ProfileFields\PROFILE ) as $group => $fields )
|
||||
{
|
||||
foreach ( $fields as $id => $field )
|
||||
{
|
||||
$profileFields[ "field_{$id}" ] = $field::stringValue( $values[ $field->name ] );
|
||||
|
||||
if ( $field instanceof \IPS\Helpers\Form\Editor )
|
||||
{
|
||||
\IPS\core\ProfileFields\Field::load( $id )->claimAttachments( $this->member->member_id );
|
||||
}
|
||||
}
|
||||
|
||||
$this->member->changedCustomFields = $profileFields;
|
||||
}
|
||||
|
||||
/* Moderator stuff */
|
||||
if ( \IPS\Member::loggedIn()->modPermission('can_modify_profiles') AND \IPS\Member::loggedIn()->member_id != $this->member->member_id)
|
||||
{
|
||||
if ( isset( $values['remove_mod_posts'] ) AND $values['remove_mod_posts'] )
|
||||
{
|
||||
$this->member->mod_posts = 0;
|
||||
}
|
||||
|
||||
if ( isset( $values['remove_restrict_post'] ) AND $values['remove_restrict_post'] )
|
||||
{
|
||||
$this->member->restrict_post = 0;
|
||||
}
|
||||
|
||||
if ( isset( $values['remove_ban'] ) AND $values['remove_ban'] )
|
||||
{
|
||||
$this->member->temp_ban = 0;
|
||||
}
|
||||
|
||||
if ( isset( $values['signature'] ) )
|
||||
{
|
||||
$this->member->signature = $values['signature'];
|
||||
}
|
||||
}
|
||||
|
||||
/* Save */
|
||||
\IPS\Db::i()->replace( 'core_pfields_content', $profileFields );
|
||||
$this->member->save();
|
||||
$this->_saveMember( $form, $values );
|
||||
|
||||
\IPS\Output::i()->redirect( $this->member->url() );
|
||||
}
|
||||
@@ -947,7 +740,205 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'editing_profile', FALSE, array( 'sprintf' => array( $this->member->name ) ) );
|
||||
\IPS\Output::i()->breadcrumb[] = array( NULL, \IPS\Member::loggedIn()->language()->addToStack( 'editing_profile', FALSE, array( 'sprintf' => array( $this->member->name ) ) ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Build Edit Form
|
||||
*
|
||||
* @return \IPS\Helpers\Form
|
||||
*/
|
||||
protected function buildEditForm()
|
||||
{
|
||||
/* Build the form */
|
||||
$form = new \IPS\Helpers\Form;
|
||||
|
||||
/* The basics */
|
||||
$form->addTab( 'profile_edit_basic_tab', 'user');
|
||||
$form->addHeader( 'profile_edit_basic_header' );
|
||||
if( \IPS\Settings::i()->post_titlechange != -1 and ( isset( \IPS\Settings::i()->post_titlechange ) and $this->member->member_posts >= \IPS\Settings::i()->post_titlechange ) )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'member_title', $this->member->member_title, FALSE, array( 'maxLength' => 64 ) ) );
|
||||
}
|
||||
|
||||
if ( \IPS\Settings::i()->profile_birthday_type !== 'none' )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Custom( 'bday', array( 'year' => $this->member->bday_year, 'month' => $this->member->bday_month, 'day' => $this->member->bday_day ), FALSE, array( 'getHtml' => function( $element )
|
||||
{
|
||||
return strtr( \IPS\Member::loggedIn()->language()->preferredDateFormat(), array(
|
||||
'DD' => \IPS\Theme::i()->getTemplate( 'members', 'core', 'global' )->bdayForm_day( $element->name, $element->value, $element->error ),
|
||||
'MM' => \IPS\Theme::i()->getTemplate( 'members', 'core', 'global' )->bdayForm_month( $element->name, $element->value, $element->error ),
|
||||
'YY' => \IPS\Theme::i()->getTemplate( 'members', 'core', 'global' )->bdayForm_year( $element->name, $element->value, $element->error ),
|
||||
'YYYY' => \IPS\Theme::i()->getTemplate( 'members', 'core', 'global' )->bdayForm_year( $element->name, $element->value, $element->error ),
|
||||
) );
|
||||
} ) ) );
|
||||
if ( \IPS\Settings::i()->profile_birthday_type == 'private' )
|
||||
{
|
||||
$form->addMessage( 'profile_birthday_display_private', 'ipsMessage ipsMessage_info' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( \IPS\Settings::i()->profile_comments and $this->member->canAccessModule( \IPS\Application\Module::get( 'core', 'status' ) ) AND !$this->member->members_bitoptions['bw_no_status_update'] )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'enable_status_updates', $this->member->pp_setting_count_comments ) );
|
||||
}
|
||||
|
||||
/* Profile fields */
|
||||
try
|
||||
{
|
||||
$values = \IPS\Db::i()->select( '*', 'core_pfields_content', array( 'member_id=?', $this->member->member_id ) )->first();
|
||||
}
|
||||
catch( \UnderflowException $e )
|
||||
{
|
||||
$values = array();
|
||||
}
|
||||
|
||||
foreach ( \IPS\core\ProfileFields\Field::fields( $values, \IPS\core\ProfileFields\Field::PROFILE ) as $group => $fields )
|
||||
{
|
||||
$form->addHeader( "core_pfieldgroups_{$group}" );
|
||||
foreach ( $fields as $field )
|
||||
{
|
||||
$form->add( $field );
|
||||
}
|
||||
}
|
||||
|
||||
/* Moderator stuff */
|
||||
if ( ( \IPS\Member::loggedIn()->modPermission('can_modify_profiles') OR \IPS\Member::loggedIn()->modPermission('can_unban') ) AND \IPS\Member::loggedIn()->member_id != $this->member->member_id )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Editor( 'signature', $this->member->signature, FALSE, array( 'app' => 'core', 'key' => 'Signatures', 'autoSaveKey' => "frontsig-" . $this->member->member_id, 'attachIds' => array( $this->member->member_id ) ) ) );
|
||||
|
||||
if ( \IPS\Member::loggedIn()->modPermission('can_unban') )
|
||||
{
|
||||
$form->addTab( 'profile_edit_moderation', 'times' );
|
||||
|
||||
if ( $this->member->mod_posts !== 0 )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'remove_mod_posts', NULL, FALSE ) );
|
||||
}
|
||||
|
||||
if ( $this->member->restrict_post !== 0 )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'remove_restrict_post', NULL, FALSE ) );
|
||||
}
|
||||
|
||||
if ( $this->member->temp_ban !== 0 )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'remove_ban', NULL, FALSE ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save Member
|
||||
*
|
||||
* @param $form
|
||||
* @param array $values
|
||||
*/
|
||||
protected function _saveMember( $form, array $values )
|
||||
{
|
||||
if( ( \IPS\Settings::i()->post_titlechange == -1 or ( isset( \IPS\Settings::i()->post_titlechange ) and $this->member->member_posts >= \IPS\Settings::i()->post_titlechange ) ) AND isset( $values['member_title'] ) )
|
||||
{
|
||||
$this->member->member_title = $values['member_title'];
|
||||
}
|
||||
|
||||
if( $values['bday'] and ( ( $values['bday']['day'] and !$values['bday']['month'] ) or ( $values['bday']['month'] and !$values['bday']['day'] ) ) )
|
||||
{
|
||||
$form->error = \IPS\Member::loggedIn()->language()->addToStack( 'bday_month_and_day_required' );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'forms', 'core' )->editContentForm( \IPS\Member::loggedIn()->language()->addToStack( 'profile_edit' ), $form );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( $values['bday'] and $values['bday']['day'] and $values['bday']['month'] )
|
||||
{
|
||||
$this->member->bday_day = $values['bday']['day'];
|
||||
$this->member->bday_month = $values['bday']['month'];
|
||||
$this->member->bday_year = $values['bday']['year'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->member->bday_day = NULL;
|
||||
$this->member->bday_month = NULL;
|
||||
$this->member->bday_year = NULL;
|
||||
}
|
||||
|
||||
if ( isset( $values['enable_status_updates'] ) )
|
||||
{
|
||||
$this->member->pp_setting_count_comments = $values['enable_status_updates'];
|
||||
|
||||
if ( $values['enable_status_updates'] )
|
||||
{
|
||||
\IPS\Content\Search\Index::i()->massUpdate( 'IPS\core\Statuses\Status', NULL, NULL, '*', NULL, NULL, $this->member->member_id );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Content\Search\Index::i()->massUpdate( 'IPS\core\Statuses\Status', NULL, NULL, '', NULL, NULL, $this->member->member_id );
|
||||
}
|
||||
}
|
||||
|
||||
/* Profile Fields */
|
||||
try
|
||||
{
|
||||
$profileFields = \IPS\Db::i()->select( '*', 'core_pfields_content', array( 'member_id=?', $this->member->member_id ) )->first();
|
||||
}
|
||||
catch( \UnderflowException $e )
|
||||
{
|
||||
$profileFields = array();
|
||||
}
|
||||
|
||||
/* If the row only contains one column (eg. member_id) then the result of the query is a string, we do not want this */
|
||||
if ( !is_array( $profileFields ) )
|
||||
{
|
||||
$profileFields = array();
|
||||
}
|
||||
|
||||
$profileFields['member_id'] = $this->member->member_id;
|
||||
|
||||
foreach ( \IPS\core\ProfileFields\Field::fields( $profileFields, \IPS\core\ProfileFields\Field::PROFILE ) as $group => $fields )
|
||||
{
|
||||
foreach ( $fields as $id => $field )
|
||||
{
|
||||
$profileFields[ "field_{$id}" ] = $field::stringValue( $values[ $field->name ] );
|
||||
|
||||
if ( $field instanceof \IPS\Helpers\Form\Editor )
|
||||
{
|
||||
\IPS\core\ProfileFields\Field::load( $id )->claimAttachments( $this->member->member_id );
|
||||
}
|
||||
}
|
||||
|
||||
$this->member->changedCustomFields = $profileFields;
|
||||
}
|
||||
|
||||
/* Moderator stuff */
|
||||
if ( \IPS\Member::loggedIn()->modPermission('can_modify_profiles') AND \IPS\Member::loggedIn()->member_id != $this->member->member_id)
|
||||
{
|
||||
if ( isset( $values['remove_mod_posts'] ) AND $values['remove_mod_posts'] )
|
||||
{
|
||||
$this->member->mod_posts = 0;
|
||||
}
|
||||
|
||||
if ( isset( $values['remove_restrict_post'] ) AND $values['remove_restrict_post'] )
|
||||
{
|
||||
$this->member->restrict_post = 0;
|
||||
}
|
||||
|
||||
if ( isset( $values['remove_ban'] ) AND $values['remove_ban'] )
|
||||
{
|
||||
$this->member->temp_ban = 0;
|
||||
}
|
||||
|
||||
if ( isset( $values['signature'] ) )
|
||||
{
|
||||
$this->member->signature = $values['signature'];
|
||||
}
|
||||
}
|
||||
|
||||
/* Save */
|
||||
\IPS\Db::i()->replace( 'core_pfields_content', $profileFields );
|
||||
$this->member->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit Photo
|
||||
*
|
||||
@@ -968,16 +959,15 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
$toggles = array( 'custom' => array( 'member_photo_upload' ), 'url' => array( 'member_photo_url' ) );
|
||||
$extra = array();
|
||||
$options = array();
|
||||
|
||||
$defaultType = $this->member->pp_photo_type;
|
||||
|
||||
/* Can we upload? */
|
||||
if ( $photoVars[0] )
|
||||
{
|
||||
$options['custom'] = 'member_photo_upload';
|
||||
$options['url'] = 'member_photo_url';
|
||||
}
|
||||
|
||||
/* We can always use URLs */
|
||||
$options['url'] = 'member_photo_url';
|
||||
|
||||
/* Can we use gallery images? */
|
||||
if ( \IPS\Application::appIsEnabled('gallery') AND $this->member->pp_photo_type == 'gallery_Images' )
|
||||
{
|
||||
@@ -988,8 +978,11 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
if ( \IPS\Settings::i()->allow_gravatars )
|
||||
{
|
||||
$options['gravatar'] = 'member_photo_gravatar';
|
||||
$extra[] = new \IPS\Helpers\Form\Email( 'photo_gravatar_email_public', $this->member->pp_gravatar ?: $this->member->email, FALSE, array( 'maxLength' => 255 ), NULL, NULL, NULL, 'member_photo_gravatar' );
|
||||
$toggles['gravatar'] = array( 'member_photo_gravatar' );
|
||||
if ( $this->member->member_id === \IPS\Member::loggedIn()->member_id or \IPS\Member::loggedIn()->modPermission('can_see_emails') )
|
||||
{
|
||||
$extra[] = new \IPS\Helpers\Form\Email( 'photo_gravatar_email_public', $this->member->pp_gravatar ?: $this->member->email, FALSE, array( 'maxLength' => 255 ), NULL, NULL, NULL, 'member_photo_gravatar' );
|
||||
$toggles['gravatar'] = array( 'member_photo_gravatar' );
|
||||
}
|
||||
}
|
||||
|
||||
/* ProfileSync (Facebook, etc.) */
|
||||
@@ -1006,19 +999,34 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
/* And of course we can always not have a photo */
|
||||
$options['none'] = 'member_photo_none';
|
||||
|
||||
/* Create that selection */
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'pp_photo_type', $this->member->pp_photo_type, TRUE, array( 'options' => $options, 'toggles' => $toggles ) ) );
|
||||
/* iOS doesn't like upload forms being hidden by a toggle; and it makes sense if we do not have a profile photo to show the upload as the selected option */
|
||||
if ( $defaultType == 'none' and $photoVars[0] )
|
||||
{
|
||||
$defaultType = 'custom';
|
||||
}
|
||||
|
||||
/* Create that selection */
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'pp_photo_type', $defaultType, TRUE, array( 'options' => $options, 'toggles' => $toggles ) ) );
|
||||
|
||||
/* Create the upload field */
|
||||
if ( $photoVars[0] )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Upload( 'member_photo_upload', NULL, FALSE, array( 'image' => array( 'maxWidth' => $photoVars[1], 'maxHeight' => $photoVars[2] ), 'storageExtension' => 'core_Profile', 'maxFileSize' => $photoVars[0] ? $photoVars[0] / 1024 : NULL ), NULL, NULL, NULL, 'member_photo_upload' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Upload( 'member_photo_upload', NULL, FALSE, array( 'image' => array( 'maxWidth' => $photoVars[1], 'maxHeight' => $photoVars[2] ), 'storageExtension' => 'core_Profile', 'maxFileSize' => $photoVars[0] ? $photoVars[0] / 1024 : NULL ), function( $val ) {
|
||||
|
||||
if ( $val instanceof \IPS\File )
|
||||
{
|
||||
$image = \IPS\Image::create( $val->contents() );
|
||||
if( $image->isAnimatedGif and !$this->member->group['g_upload_animated_photos'] )
|
||||
{
|
||||
throw new \DomainException('member_photo_upload_no_animated');
|
||||
}
|
||||
}
|
||||
}, NULL, NULL, 'member_photo_upload' ) );
|
||||
|
||||
/* Create the URL */
|
||||
$form->add( new \IPS\Helpers\Form\Url( 'member_photo_url', NULL, FALSE, array( 'file' => 'core_Profile', 'allowedMimes' => 'image/*', 'maxFileSize' => $photoVars[0] ? $photoVars[0] / 1024 : NULL, 'maxDimensions' => array( 'width' => $photoVars[1], 'height' => $photoVars[2] ) ), NULL, NULL, NULL, 'member_photo_url' ) );
|
||||
}
|
||||
|
||||
/* Create the URL */
|
||||
$form->add( new \IPS\Helpers\Form\Url( 'member_photo_url', NULL, FALSE, array( 'file' => 'core_Profile', 'allowedMimes' => 'image/*', 'maxFileSize' => $photoVars[0] ? $photoVars[0] / 1024 : NULL ), NULL, NULL, NULL, 'member_photo_url' ) );
|
||||
|
||||
|
||||
/* Add additional elements */
|
||||
foreach ( $extra as $element )
|
||||
{
|
||||
@@ -1028,12 +1036,24 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
/* Handle submissions */
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$this->member->pp_photo_type = $values['pp_photo_type'] === 'none' ? NULL : $values['pp_photo_type'];
|
||||
$this->member->pp_photo_type = $values['pp_photo_type'];
|
||||
|
||||
/* If we are changing our photo, it is safe to assume that any services currently set to sync should no longer do so */
|
||||
$services = \IPS\core\ProfileSync\ProfileSyncAbstract::services();
|
||||
|
||||
if ( !empty( $services ) )
|
||||
{
|
||||
foreach( $services AS $class )
|
||||
{
|
||||
$obj = new $class( $this->member );
|
||||
$obj->save( array( 'profilesync_photo' => FALSE ) );
|
||||
}
|
||||
}
|
||||
|
||||
switch ( $values['pp_photo_type'] )
|
||||
{
|
||||
case 'custom':
|
||||
if ( $values['member_photo_upload'] )
|
||||
if ( $photoVars[0] and $values['member_photo_upload'] )
|
||||
{
|
||||
if ( (string) $values['member_photo_upload'] !== '' )
|
||||
{
|
||||
@@ -1050,7 +1070,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
break;
|
||||
|
||||
case 'url':
|
||||
if( $values['member_photo_url'] )
|
||||
if( $photoVars[0] and $values['member_photo_url'] )
|
||||
{
|
||||
$this->member->pp_photo_type = 'custom';
|
||||
$this->member->pp_main_photo = NULL;
|
||||
@@ -1070,7 +1090,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
break;
|
||||
|
||||
case 'gravatar':
|
||||
$this->member->pp_gravatar = ( $values['photo_gravatar_email_public'] === $this->member->email ) ? NULL : $values['photo_gravatar_email_public'];
|
||||
$this->member->pp_gravatar = ( !isset( $values['photo_gravatar_email_public'] ) or $values['photo_gravatar_email_public'] === $this->member->email ) ? NULL : $values['photo_gravatar_email_public'];
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1131,6 +1151,11 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
*/
|
||||
protected function cropPhoto()
|
||||
{
|
||||
if ( !\IPS\Member::loggedIn()->modPermission('can_modify_profiles') and ( \IPS\Member::loggedIn()->member_id !== $this->member->member_id or !$this->member->group['g_edit_profile'] ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_permission_edit_profile', '2C138/F', 403, '' );
|
||||
}
|
||||
|
||||
if( !$this->member->pp_main_photo )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_photo_to_crop', '2C138/C', 404, '' );
|
||||
@@ -1180,10 +1205,13 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
}
|
||||
|
||||
/* Save the new */
|
||||
$cropped = \IPS\File::create( 'core_Profile', $original->filename, (string) $image );
|
||||
$cropped = \IPS\File::create( 'core_Profile', $original->originalFilename, (string) $image );
|
||||
$this->member->pp_thumb_photo = (string) $cropped->thumbnail( 'core_Profile', \IPS\PHOTO_THUMBNAIL_SIZE, \IPS\PHOTO_THUMBNAIL_SIZE );
|
||||
$this->member->save();
|
||||
|
||||
|
||||
/* Delete the temporary full size cropped image */
|
||||
$cropped->delete();
|
||||
|
||||
/* Edited member, so clear widget caches (stats, widgets that contain photos, names and so on) */
|
||||
\IPS\Widget::deleteCaches();
|
||||
|
||||
@@ -1291,7 +1319,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
{
|
||||
try
|
||||
{
|
||||
$item = ( \IPS\Request::i()->type == 'status' ) ? \IPS\core\Statuses\Status::load( \IPS\Request::i()->status ) : \IPS\core\Statuses\Reply::load( \IPS\Request::i()->status );
|
||||
$item = ( \IPS\Request::i()->type == 'status' ) ? \IPS\core\Statuses\Status::load( \IPS\Request::i()->status ) : \IPS\core\Statuses\Reply::load( \IPS\Request::i()->reply );
|
||||
|
||||
\IPS\Output::i()->output = $item->reputationTable();
|
||||
}
|
||||
@@ -1368,7 +1396,12 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
|
||||
$limit = array( ( $page - 1 ) * 50, 50 );
|
||||
$followers = $this->member->followers( ( \IPS\Member::loggedIn()->isAdmin() OR \IPS\Member::loggedIn()->member_id === $this->member->member_id ) ? \IPS\Member::FOLLOW_PUBLIC + \IPS\Member::FOLLOW_ANONYMOUS : \IPS\Member::FOLLOW_PUBLIC, array( 'immediate', 'daily', 'weekly' ), NULL, $limit, 'name' );
|
||||
|
||||
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'profile' )->followers( $this->member, $followers ) );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('members_followers', FALSE, array( 'sprintf' => array( $this->member->name ) ) );
|
||||
\IPS\Output::i()->breadcrumb[] = array( NULL, \IPS\Member::loggedIn()->language()->addToStack('members_followers', FALSE, array( 'sprintf' => array( $this->member->name ) ) ) );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'profile' )->allFollowers( $this->member, $followers );
|
||||
@@ -1392,10 +1425,45 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
*/
|
||||
protected function _coverPhotoSet( \IPS\Helpers\CoverPhoto $photo )
|
||||
{
|
||||
/* If we are changing our cover photo, it is safe to assume that any services currently set to sync should no longer do so */
|
||||
$services = \IPS\core\ProfileSync\ProfileSyncAbstract::services();
|
||||
|
||||
if ( !empty( $services ) )
|
||||
{
|
||||
foreach( $services AS $class )
|
||||
{
|
||||
$obj = new $class( $this->member );
|
||||
if ( $obj->connected() )
|
||||
{
|
||||
$obj->save( array( 'profilesync_cover' => FALSE ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->member->pp_cover_photo = (string) $photo->file;
|
||||
$this->member->pp_cover_offset = $photo->offset;
|
||||
$this->member->pp_cover_offset = (int) $photo->offset;
|
||||
$this->member->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Name History
|
||||
*/
|
||||
protected function namehistory()
|
||||
{
|
||||
if ( !\IPS\Member::loggedIn()->group['g_view_displaynamehistory'] )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '1C138/G', 403, '' );
|
||||
}
|
||||
$table = new \IPS\Helpers\Table\Db( 'core_dnames_change', $this->member->url()->setQueryString( 'do', 'namehistory' ), array( 'dname_member_id=?', $this->member->member_id ) );
|
||||
$table->tableTemplate = array( \IPS\Theme::i()->getTemplate( 'profile' ), 'nameHistoryTable' );
|
||||
$table->rowsTemplate = array( \IPS\Theme::i()->getTemplate( 'profile' ), 'nameHistoryRows' );
|
||||
$table->sortBy = 'dname_date';
|
||||
$table->sortDirection = 'desc';
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addtoStack( 'members_dname_history', FALSE, array( 'sprintf' => ( $this->member->name ) ) );
|
||||
\IPS\Output::i()->output = $table;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Cover Photo
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Messenger
|
||||
* @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 5 Jul 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -47,7 +47,7 @@ class _messenger extends \IPS\Content\Controller
|
||||
|
||||
if ( \IPS\Member::loggedIn()->members_disable_pm AND \IPS\Member::loggedIn()->members_disable_pm != 2 AND \IPS\Request::i()->do != 'enableMessenger' )
|
||||
{
|
||||
\IPS\Output::i()->error( 'messenger_disabled_can_enable', '2C137/A', 403, '' );
|
||||
\IPS\Output::i()->error( \IPS\Member::loggedIn()->language()->addToStack('messenger_disabled_can_enable', FALSE, array( 'sprintf' => array( \IPS\Http\URL::internal( 'app=core&module=messaging&controller=messenger&do=enableMessenger', 'front', 'messaging' )->csrf() ) ) ), '2C137/A', 403, '' );
|
||||
}
|
||||
else if ( \IPS\Member::loggedIn()->members_disable_pm == 2 )
|
||||
{
|
||||
@@ -60,7 +60,6 @@ class _messenger extends \IPS\Content\Controller
|
||||
{
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'jquery/jquery-ui.js', 'core', 'interface' ) );
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'jquery/jquery-touchpunch.js', 'core', 'interface' ) );
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'jquery/jquery.slimscroll.js', 'core', 'interface' ) );
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_model_messages.js', 'core' ) );
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js('front_messages.js', 'core' ) );
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/messaging.css' ) );
|
||||
@@ -68,7 +67,7 @@ class _messenger extends \IPS\Content\Controller
|
||||
}
|
||||
|
||||
/* Set Session Location */
|
||||
\IPS\Session::i()->setLocation( \IPS\Http\Url::internal( 'app=core&module=messaging&controller=messenger', NULL, 'messenger' ), array(), 'loc_using_messenger' );
|
||||
\IPS\Session::i()->setLocation( \IPS\Http\Url::internal( 'app=core&module=messaging&controller=messenger', NULL, 'messaging' ), array(), 'loc_using_messenger' );
|
||||
|
||||
parent::execute();
|
||||
}
|
||||
@@ -86,7 +85,7 @@ class _messenger extends \IPS\Content\Controller
|
||||
$folders = array( 'myconvo' => \IPS\Member::loggedIn()->language()->addToStack('messenger_folder_inbox') );
|
||||
if ( \IPS\Member::loggedIn()->pconversation_filters )
|
||||
{
|
||||
$folders = array_merge( $folders, array_filter( json_decode( \IPS\Member::loggedIn()->pconversation_filters, TRUE ) ) );
|
||||
$folders = $folders + array_filter( json_decode( \IPS\Member::loggedIn()->pconversation_filters, TRUE ) );
|
||||
}
|
||||
|
||||
/* Are we looking at a specific folder? */
|
||||
@@ -116,6 +115,30 @@ class _messenger extends \IPS\Content\Controller
|
||||
try
|
||||
{
|
||||
$conversation = \IPS\core\Messenger\Conversation::loadAndCheckPerms( \IPS\Request::i()->id );
|
||||
|
||||
/* If this message triggered a PM popup and we view it directly, it will no longer be marked as unread but msg_show_notification for
|
||||
the member will still be set, causing the next oldest PM to show in a popup erroneously. If this is the latest unread PM, reset
|
||||
msg_show_notification now to prevent the popup from showing. */
|
||||
if( \IPS\Member::loggedIn()->msg_show_notification )
|
||||
{
|
||||
$latestConversation = NULL;
|
||||
|
||||
try
|
||||
{
|
||||
$latestConversation = \IPS\Db::i()->select( 'map_topic_id', 'core_message_topic_user_map', array( 'map_user_id=? AND map_user_active=1 AND map_has_unread=1 AND map_ignore_notification=0', \IPS\Member::loggedIn()->member_id ), 'map_last_topic_reply DESC' )->first();
|
||||
}
|
||||
catch ( \UnderflowException $e ) { }
|
||||
|
||||
if( $latestConversation == $conversation->id )
|
||||
{
|
||||
\IPS\Member::loggedIn()->msg_show_notification = FALSE;
|
||||
\IPS\Member::loggedIn()->save();
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Db::i()->update( 'core_message_topic_user_map', array( 'map_read_time' => time(), 'map_has_unread' => 0 ), array( 'map_user_id=? AND map_topic_id=?', \IPS\Member::loggedIn()->member_id, $conversation->id ) );
|
||||
\IPS\core\Messenger\Conversation::rebuildMessageCounts( \IPS\Member::loggedIn() );
|
||||
|
||||
if ( \IPS\Request::i()->isAjax() and \IPS\Request::i()->getRow )
|
||||
{
|
||||
$row = \IPS\Db::i()->select(
|
||||
@@ -127,15 +150,14 @@ class _messenger extends \IPS\Content\Controller
|
||||
'core_message_posts.msg_topic_id=core_message_topics.mt_id'
|
||||
)->join(
|
||||
'core_message_topic_user_map',
|
||||
'core_message_topic_user_map.map_topic_id=core_message_topics.mt_id'
|
||||
'core_message_topic_user_map.map_topic_id=core_message_topics.mt_id AND core_message_topic_user_map.map_user_id=' . intval( \IPS\Member::loggedIn()->member_id )
|
||||
)->first();
|
||||
$row['last_message'] = \IPS\core\Messenger\Conversation::load( $row['mt_id'] )->comments( 1, 0, 'date', 'desc' );
|
||||
$row['participants'] = \IPS\core\Messenger\Conversation::load( $row['mt_id'] )->participantBlurb();
|
||||
|
||||
\IPS\Output::i()->json( \IPS\Theme::i()->getTemplate( 'messaging' )->messageListRow( $row, FALSE ) );
|
||||
\IPS\Output::i()->json( \IPS\Theme::i()->getTemplate( 'messaging' )->messageListRow( $row, FALSE, $folders ) );
|
||||
}
|
||||
|
||||
\IPS\Db::i()->update( 'core_message_topic_user_map', array( 'map_read_time' => time(), 'map_has_unread' => 0 ), array( 'map_user_id=? AND map_topic_id=?', \IPS\Member::loggedIn()->member_id, $conversation->id ) );
|
||||
\IPS\core\Messenger\Conversation::rebuildMessageCounts( \IPS\Member::loggedIn() );
|
||||
|
||||
\IPS\Output::i()->title = $conversation->title;
|
||||
$baseUrl = $baseUrl->setQueryString( 'id', \IPS\Request::i()->id );
|
||||
|
||||
@@ -194,35 +216,68 @@ class _messenger extends \IPS\Content\Controller
|
||||
}
|
||||
|
||||
/* Do we need a filter? */
|
||||
$where = array( array( 'map_user_id=? AND map_user_active=1', \IPS\Member::loggedIn()->member_id ) );
|
||||
$where = array( array( 'core_message_topic_user_map.map_user_id=? AND core_message_topic_user_map.map_user_active=1', \IPS\Member::loggedIn()->member_id ) );
|
||||
if ( \IPS\Request::i()->filter == 'mine' )
|
||||
{
|
||||
$where[] = array( 'map_is_starter=1' );
|
||||
$where[] = array( 'core_message_topic_user_map.map_is_starter=1' );
|
||||
}
|
||||
elseif( \IPS\Request::i()->filter == 'not_mine' )
|
||||
{
|
||||
$where[] = array( 'map_is_starter=0' );
|
||||
$where[] = array( 'core_message_topic_user_map.map_is_starter=0' );
|
||||
}
|
||||
|
||||
elseif( \IPS\Request::i()->filter == 'read' )
|
||||
{
|
||||
$where[] = array( 'core_message_topic_user_map.map_has_unread=0' );
|
||||
}
|
||||
elseif( \IPS\Request::i()->filter == 'not_read' )
|
||||
{
|
||||
$where[] = array( 'core_message_topic_user_map.map_has_unread=1' );
|
||||
}
|
||||
|
||||
/* Add a folder filter */
|
||||
if ( !isset( \IPS\Request::i()->overview ) )
|
||||
{
|
||||
if ( !is_null( $folder ) AND isset( $folders[ $folder ] ) )
|
||||
{
|
||||
$where[] = array( 'map_folder_id=?', $folder );
|
||||
$where[] = array( 'core_message_topic_user_map.map_folder_id=?', $folder );
|
||||
}
|
||||
else
|
||||
{
|
||||
$where[] = array( 'map_folder_id=?', 'myconvo' );
|
||||
$where[] = array( 'core_message_topic_user_map.map_folder_id=?', 'myconvo' );
|
||||
}
|
||||
}
|
||||
|
||||
/* If we're searching, get the results */
|
||||
$perPage = 25;
|
||||
$perPage = 25;
|
||||
$iterator = array();
|
||||
|
||||
if ( \IPS\Request::i()->q )
|
||||
{
|
||||
$where[] = array( "( MATCH(core_message_topics.mt_title) AGAINST ('" . \IPS\Db::i()->escape_string( \IPS\Request::i()->q ) . "' IN BOOLEAN MODE) OR
|
||||
MATCH(core_message_posts.msg_post) AGAINST ('" . \IPS\Db::i()->escape_string( \IPS\Request::i()->q ) . "' IN BOOLEAN MODE) )" );
|
||||
$query = array();
|
||||
if ( isset( \IPS\Request::i()->search ) and $searchValues = \IPS\Request::i()->valueFromArray('search') )
|
||||
{
|
||||
if ( isset( $searchValues['topic'] ) )
|
||||
{
|
||||
$query[] = \IPS\Content\Search\Mysql\Query::matchClause( "core_message_topics.mt_title", \IPS\Request::i()->q, '+', FALSE );
|
||||
}
|
||||
if ( isset( $searchValues['post'] ) )
|
||||
{
|
||||
$query[] = \IPS\Content\Search\Mysql\Query::matchClause( "core_message_posts.msg_post", \IPS\Request::i()->q, '+', FALSE );
|
||||
}
|
||||
if ( isset( $searchValues['recipient'] ) )
|
||||
{
|
||||
$query[] = "receiving_member.name LIKE '%" . \IPS\Db::i()->escape_string( \IPS\Request::i()->q ) . "%'";
|
||||
}
|
||||
if ( isset( $searchValues['sender'] ) )
|
||||
{
|
||||
$query[] = "sending_member.name LIKE '%" . \IPS\Db::i()->escape_string( \IPS\Request::i()->q ) . "%'";
|
||||
}
|
||||
|
||||
if ( count( $query ) )
|
||||
{
|
||||
$where[] = '(' . implode( ' OR ', $query ) . ')';
|
||||
}
|
||||
}
|
||||
|
||||
/* Get a count */
|
||||
try
|
||||
@@ -236,6 +291,22 @@ class _messenger extends \IPS\Content\Controller
|
||||
'core_message_topic_user_map',
|
||||
'core_message_topic_user_map.map_topic_id=core_message_topics.mt_id'
|
||||
)
|
||||
->join(
|
||||
array( 'core_message_topic_user_map', 'sender_map' ),
|
||||
'sender_map.map_topic_id=core_message_topics.mt_id AND sender_map.map_is_starter=1'
|
||||
)
|
||||
->join(
|
||||
array( 'core_message_topic_user_map', 'receiver_map' ),
|
||||
'receiver_map.map_topic_id=core_message_topics.mt_id AND receiver_map.map_is_starter=0'
|
||||
)
|
||||
->join(
|
||||
array( 'core_members', 'sending_member' ),
|
||||
'sending_member.member_id=sender_map.map_user_id'
|
||||
)
|
||||
->join(
|
||||
array( 'core_members', 'receiving_member' ),
|
||||
'receiving_member.member_id=receiver_map.map_user_id'
|
||||
)
|
||||
->first();
|
||||
}
|
||||
catch( \UnderflowException $e )
|
||||
@@ -243,38 +314,75 @@ class _messenger extends \IPS\Content\Controller
|
||||
$count = 0;
|
||||
}
|
||||
|
||||
/* Get iterator */
|
||||
$iterator = \IPS\Db::i()->select(
|
||||
'core_message_topic_user_map.*, core_message_topics.*',
|
||||
'core_message_posts',
|
||||
$where,
|
||||
( in_array( \IPS\Request::i()->sortBy, array( 'mt_last_post_time', 'mt_start_time', 'mt_replies' ) ) ? \IPS\Request::i()->sortBy : 'mt_last_post_time' ) . ' DESC',
|
||||
array( ( intval( \IPS\Request::i()->listPage ?: 1 ) - 1 ) * $perPage, $perPage ),
|
||||
'msg_topic_id'
|
||||
)->join(
|
||||
'core_message_topics',
|
||||
'core_message_posts.msg_topic_id=core_message_topics.mt_id'
|
||||
)->join(
|
||||
'core_message_topic_user_map',
|
||||
'core_message_topic_user_map.map_topic_id=core_message_topics.mt_id'
|
||||
);
|
||||
/* Performance: if count is 0, don't bother selecting ... it's a wasted query */
|
||||
if( $count )
|
||||
{
|
||||
/* Because of strict group by, we first need to select the ids, then grab those topics */
|
||||
$sortColumn = ( in_array( \IPS\Request::i()->sortBy, array( 'mt_last_post_time', 'mt_start_time', 'mt_replies' ) ) ? \IPS\Request::i()->sortBy : 'mt_last_post_time' );
|
||||
$iterator = \IPS\Db::i()->select(
|
||||
'core_message_posts.msg_topic_id',
|
||||
'core_message_posts',
|
||||
$where,
|
||||
$sortColumn . ' DESC',
|
||||
array( ( intval( \IPS\Request::i()->listPage ?: 1 ) - 1 ) * $perPage, $perPage ),
|
||||
array( 'msg_topic_id', $sortColumn )
|
||||
)->join(
|
||||
'core_message_topics',
|
||||
'core_message_posts.msg_topic_id=core_message_topics.mt_id'
|
||||
)->join(
|
||||
'core_message_topic_user_map',
|
||||
'core_message_topic_user_map.map_topic_id=core_message_topics.mt_id'
|
||||
)
|
||||
->join(
|
||||
array( 'core_message_topic_user_map', 'sender_map' ),
|
||||
'sender_map.map_topic_id=core_message_topics.mt_id AND sender_map.map_is_starter=1'
|
||||
)
|
||||
->join(
|
||||
array( 'core_message_topic_user_map', 'receiver_map' ),
|
||||
'receiver_map.map_topic_id=core_message_topics.mt_id AND receiver_map.map_is_starter=0'
|
||||
)
|
||||
->join(
|
||||
array( 'core_members', 'sending_member' ),
|
||||
'sending_member.member_id=sender_map.map_user_id'
|
||||
)
|
||||
->join(
|
||||
array( 'core_members', 'receiving_member' ),
|
||||
'receiving_member.member_id=receiver_map.map_user_id'
|
||||
);
|
||||
|
||||
/* Get iterator */
|
||||
$iterator = \IPS\Db::i()->select(
|
||||
'core_message_topic_user_map.*, core_message_topics.*',
|
||||
'core_message_topic_user_map',
|
||||
array( 'map_topic_id IN(' . implode( ',', iterator_to_array( $iterator ) ) . ')' ),
|
||||
( in_array( \IPS\Request::i()->sortBy, array( 'mt_last_post_time', 'mt_start_time', 'mt_replies' ) ) ? \IPS\Request::i()->sortBy : 'mt_last_post_time' ) . ' DESC',
|
||||
array( ( intval( \IPS\Request::i()->listPage ?: 1 ) - 1 ) * $perPage, $perPage )
|
||||
)->join(
|
||||
'core_message_topics',
|
||||
'core_message_topic_user_map.map_topic_id=core_message_topics.mt_id'
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get a count */
|
||||
$count = \IPS\Db::i()->select( 'COUNT(*)', 'core_message_topic_user_map', $where )->first();
|
||||
|
||||
/* Get iterator */
|
||||
$iterator = \IPS\Db::i()->select(
|
||||
'core_message_topic_user_map.*, core_message_topics.*',
|
||||
'core_message_topic_user_map',
|
||||
$where,
|
||||
( in_array( \IPS\Request::i()->sortBy, array( 'mt_last_post_time', 'mt_start_time', 'mt_replies' ) ) ? \IPS\Request::i()->sortBy : 'mt_last_post_time' ) . ' DESC',
|
||||
array( ( intval( \IPS\Request::i()->listPage ?: 1 ) - 1 ) * $perPage, $perPage )
|
||||
)->join(
|
||||
'core_message_topics',
|
||||
'core_message_topic_user_map.map_topic_id=core_message_topics.mt_id'
|
||||
);
|
||||
/* Performance: if $count is 0, don't bother selecting ... it's a wasted query */
|
||||
if( $count )
|
||||
{
|
||||
/* Get iterator */
|
||||
$iterator = \IPS\Db::i()->select(
|
||||
'core_message_topic_user_map.*, core_message_topics.*',
|
||||
'core_message_topic_user_map',
|
||||
$where,
|
||||
( in_array( \IPS\Request::i()->sortBy, array( 'mt_last_post_time', 'mt_start_time', 'mt_replies' ) ) ? \IPS\Request::i()->sortBy : 'mt_last_post_time' ) . ' DESC',
|
||||
array( ( intval( \IPS\Request::i()->listPage ?: 1 ) - 1 ) * $perPage, $perPage )
|
||||
)->join(
|
||||
'core_message_topics',
|
||||
'core_message_topic_user_map.map_topic_id=core_message_topics.mt_id'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/* Build the message list */
|
||||
@@ -292,7 +400,15 @@ class _messenger extends \IPS\Content\Controller
|
||||
\IPS\core\Messenger\Conversation::rebuildMessageCounts( \IPS\Member::loggedIn() );
|
||||
|
||||
/* Display */
|
||||
$pagination = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $baseUrl->setQueryString('_list', 1), ceil( $count / $perPage ), ( \IPS\Request::i()->listPage ?: 1 ), $perPage, TRUE, 'listPage' );
|
||||
$listUrl = $baseUrl;
|
||||
$baseUrl = $baseUrl->setQueryString('_list', 1);
|
||||
|
||||
if( isset( \IPS\Request::i()->filter ) )
|
||||
{
|
||||
$baseUrl = $baseUrl->setQueryString('filter', \IPS\Request::i()->filter );
|
||||
}
|
||||
|
||||
$pagination = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $baseUrl, ceil( $count / $perPage ), ( \IPS\Request::i()->listPage ?: 1 ), $perPage, TRUE, 'listPage' );
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
if( \IPS\Request::i()->id )
|
||||
@@ -301,11 +417,15 @@ class _messenger extends \IPS\Content\Controller
|
||||
}
|
||||
elseif( \IPS\Request::i()->overview )
|
||||
{
|
||||
\IPS\Output::i()->json( array( 'data' => \IPS\Theme::i()->getTemplate('messaging')->messageListRows( $conversations, $pagination, TRUE ) ) );
|
||||
\IPS\Output::i()->json( array(
|
||||
'data' => \IPS\Theme::i()->getTemplate('messaging')->messageListRows( $conversations, $pagination, TRUE, $folders ),
|
||||
'pagination' => $pagination,
|
||||
'listBaseUrl' => $listUrl->setQueryString( array( 'sortBy' => \IPS\Request::i()->sortBy, 'filter' => \IPS\Request::i()->filter ) )->stripQueryString( 'id' )
|
||||
) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate('messaging')->messageListRows( $conversations, $pagination, TRUE ), 200, 'text/html' );
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate('messaging')->messageListRows( $conversations, $pagination, TRUE, $folders ), 200, 'text/html' );
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -328,6 +448,42 @@ class _messenger extends \IPS\Content\Controller
|
||||
\IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupTemplate' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Move messages form
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function moveForm()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
$folders = json_decode( \IPS\Member::loggedIn()->pconversation_filters, TRUE );
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->add( new \IPS\Helpers\Form\Select( 'move_message_to', NULL, FALSE, array( 'options' => array_merge( array( 'myconvo' => 'inbox' ), $folders ) ) ) );
|
||||
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$ids = explode( ',', \IPS\Request::i()->ids );
|
||||
foreach( $ids as $id )
|
||||
{
|
||||
try
|
||||
{
|
||||
$conversation = \IPS\core\Messenger\Conversation::loadAndCheckPerms( $id );
|
||||
$conversation->moveConversation( \IPS\Request::i()->move_message_to );
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=messaging&controller=messenger&folder=' . \IPS\Request::i()->move_message_to, 'front', 'messenger' ) );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = 'messenger_move';
|
||||
\IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupTemplate' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Folder
|
||||
*
|
||||
@@ -335,6 +491,8 @@ class _messenger extends \IPS\Content\Controller
|
||||
*/
|
||||
protected function addFolder()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'messenger_add_folder_name', NULL, TRUE ) );
|
||||
if ( $values = $form->values() )
|
||||
@@ -386,6 +544,9 @@ class _messenger extends \IPS\Content\Controller
|
||||
protected function deleteFolder()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
/* Make sure the user confirmed the deletion */
|
||||
\IPS\Request::i()->confirmedDelete();
|
||||
|
||||
\IPS\Db::i()->update( 'core_message_topic_user_map', array( 'map_user_active' => FALSE, 'map_left_time' => time() ), array( 'map_user_id=? AND map_folder_id=?', \IPS\Member::loggedIn()->member_id, \IPS\Request::i()->folder ) );
|
||||
|
||||
@@ -436,7 +597,9 @@ class _messenger extends \IPS\Content\Controller
|
||||
*/
|
||||
protected function renameFolder()
|
||||
{
|
||||
$folders = json_decode( \IPS\Member::loggedIn()->pconversation_filters, TRUE );
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
$folders = json_decode( \IPS\Member::loggedIn()->pconversation_filters, TRUE );
|
||||
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'messenger_add_folder_name', $folders[ \IPS\Request::i()->folder ], TRUE ) );
|
||||
@@ -472,6 +635,8 @@ class _messenger extends \IPS\Content\Controller
|
||||
*/
|
||||
protected function blockParticipant()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
try
|
||||
{
|
||||
$conversation = \IPS\core\Messenger\Conversation::loadAndCheckPerms( \IPS\Request::i()->id );
|
||||
@@ -513,6 +678,8 @@ class _messenger extends \IPS\Content\Controller
|
||||
*/
|
||||
protected function addParticipant()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
try
|
||||
{
|
||||
$conversation = \IPS\core\Messenger\Conversation::loadAndCheckPerms( \IPS\Request::i()->id );
|
||||
@@ -525,7 +692,8 @@ class _messenger extends \IPS\Content\Controller
|
||||
{
|
||||
foreach ( explode( ',', \IPS\Request::i()->member_names ) as $name )
|
||||
{
|
||||
$memberToAdd = \IPS\Member::load( $name, 'name' );
|
||||
/* We have to html_entity_decode because the javascript code sends the encoded name here */
|
||||
$memberToAdd = \IPS\Member::load( html_entity_decode( $name, ENT_QUOTES, 'UTF-8' ), 'name' );
|
||||
if ( $memberToAdd->member_id )
|
||||
{
|
||||
$members[] = $memberToAdd;
|
||||
@@ -564,6 +732,11 @@ class _messenger extends \IPS\Content\Controller
|
||||
throw new \InvalidArgumentException( \IPS\Member::loggedIn()->language()->addToStack('messenger_member_left', FALSE, array( 'sprintf' => array( $member->name ) ) ) );
|
||||
}
|
||||
|
||||
if ( !$conversation::memberCanReceiveNewMessage( $member, \IPS\Member::loggedIn() ) )
|
||||
{
|
||||
throw new \InvalidArgumentException( \IPS\Member::loggedIn()->language()->addToStack('meesnger_err_bad_recipient', FALSE, array( 'sprintf' => array( $member->name ) ) ) );
|
||||
}
|
||||
|
||||
$maps = $conversation->authorize( $member );
|
||||
$ids[] = $member->member_id;
|
||||
|
||||
@@ -615,6 +788,8 @@ class _messenger extends \IPS\Content\Controller
|
||||
*/
|
||||
protected function notifications()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
try
|
||||
{
|
||||
$conversation = \IPS\core\Messenger\Conversation::loadAndCheckPerms( \IPS\Request::i()->id );
|
||||
@@ -634,14 +809,12 @@ class _messenger extends \IPS\Content\Controller
|
||||
*/
|
||||
protected function move()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
try
|
||||
{
|
||||
$conversation = \IPS\core\Messenger\Conversation::loadAndCheckPerms( \IPS\Request::i()->id );
|
||||
|
||||
if ( in_array( \IPS\Request::i()->to, array_merge( array( 'myconvo' ), array_keys( json_decode( \IPS\Member::loggedIn()->pconversation_filters, TRUE ) ) ) ) )
|
||||
{
|
||||
\IPS\Db::i()->update( 'core_message_topic_user_map', array( 'map_folder_id' => \IPS\Request::i()->to ), array( 'map_user_id=? AND map_topic_id=?', \IPS\Member::loggedIn()->member_id, $conversation->id ) );
|
||||
}
|
||||
$conversation->moveConversation( \IPS\Request::i()->to );
|
||||
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
@@ -665,6 +838,8 @@ class _messenger extends \IPS\Content\Controller
|
||||
*/
|
||||
protected function leaveConversation()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
try
|
||||
{
|
||||
$ids = \IPS\Request::i()->id;
|
||||
@@ -706,9 +881,10 @@ class _messenger extends \IPS\Content\Controller
|
||||
*/
|
||||
protected function enableMessenger()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
\IPS\Member::loggedIn()->members_disable_pm = 0;
|
||||
\IPS\Member::loggedIn()->save();
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=messaging&controller=messenger', 'front', 'messenger' ), 'messenger_enabled' );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=messaging&controller=messenger', 'front', 'messaging' ), 'messenger_enabled' );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Moderator Control Panel
|
||||
* @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 24 Oct 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -113,6 +113,18 @@ class _modcp extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the count for the approval queue. If the community has a lot of data in the search index, thid can take a long
|
||||
time, so we cache for a short while */
|
||||
try
|
||||
{
|
||||
$approvalQueueCount = \IPS\Data\Cache::i()->getWithExpire( 'modCpApprovalQueueCount_' . \IPS\Member::loggedIn()->member_id, TRUE );
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
$approvalQueueCount = \IPS\Content\Search\Query::init()->setHiddenFilter( \IPS\Content\Search\Query::HIDDEN_UNAPPROVED )->count();
|
||||
\IPS\Data\Cache::i()->storeWithExpire( 'modCpApprovalQueueCount_' . \IPS\Member::loggedIn()->member_id, $approvalQueueCount, \IPS\DateTime::create()->add( new \DateInterval( 'PT15M' ) ), TRUE );
|
||||
}
|
||||
|
||||
/* Display */
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/modcp.css' ) );
|
||||
@@ -125,9 +137,7 @@ class _modcp extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'modcp' )->template( $content, $tabs, $activeTab, $types, \IPS\Content\Search\Query::init()->setHiddenFilter( \IPS\Content\Search\Query::HIDDEN_UNAPPROVED )->count() );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'modcp' )->template( $content, $tabs, $activeTab, $types, $approvalQueueCount );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Online Users
|
||||
* @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 21 Aug 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -37,18 +37,38 @@ class _online extends \IPS\Dispatcher\Controller
|
||||
\IPS\Session\Front::i()->setTheme( \IPS\Member::loggedIn()->skin ?: 0 );
|
||||
session_write_close();
|
||||
|
||||
$notInMyName = array();
|
||||
foreach( \IPS\Member\Group::groups() as $group )
|
||||
{
|
||||
if ( $group->g_hide_online_list )
|
||||
{
|
||||
$notInMyName[] = $group->g_id;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initial filters */
|
||||
$where = array(
|
||||
array( "core_sessions.running_time>?", \IPS\DateTime::create()->sub( new \DateInterval( 'PT30M' ) )->getTimeStamp() ),
|
||||
array( "core_sessions.login_type!=?", \IPS\Session\Front::LOGIN_TYPE_SPIDER )
|
||||
$subWhere = array(
|
||||
array( "s.running_time>?", \IPS\DateTime::create()->sub( new \DateInterval( 'PT30M' ) )->getTimeStamp() ),
|
||||
array( "s.login_type!=?", \IPS\Session\Front::LOGIN_TYPE_SPIDER )
|
||||
);
|
||||
if ( !\IPS\Member::loggedIn()->isAdmin() )
|
||||
{
|
||||
$where[] = array( "core_sessions.login_type!=?", \IPS\Session\Front::LOGIN_TYPE_ANONYMOUS );
|
||||
$subWhere[] = array( "s.login_type!=?", \IPS\Session\Front::LOGIN_TYPE_ANONYMOUS );
|
||||
}
|
||||
|
||||
$where[] = "core_groups.g_hide_online_list=0";
|
||||
|
||||
if ( count( $notInMyName ) )
|
||||
{
|
||||
$subWhere[] = array( \IPS\Db::i()->in( 's.member_group', $notInMyName, TRUE ) );
|
||||
}
|
||||
|
||||
/* Ok, this looks odd, but the ONLY_FULL_GROUP_BY bites us here, so selecting max(id) allows us to return a session ID even though we're grouping on member_id */
|
||||
$where = array( array( "( core_sessions.id IN(?) OR ( core_sessions.member_id IS NULL AND core_sessions.login_type != ? AND core_sessions.running_time > ?) )", \IPS\Db::i()->select( 'MAX(id)', array( 'core_sessions', 's' ), $subWhere, NULL, NULL, 'member_id' ), \IPS\Session\Front::LOGIN_TYPE_SPIDER, \IPS\DateTime::create()->sub( new \DateInterval( 'PT30M' ) )->getTimeStamp() ) );
|
||||
|
||||
if ( count( $notInMyName ) )
|
||||
{
|
||||
$where[] = array( \IPS\Db::i()->in( 'core_sessions.member_group', $notInMyName, TRUE ) );
|
||||
}
|
||||
|
||||
/* Create the table */
|
||||
$table = new \IPS\Helpers\Table\Db( 'core_sessions', \IPS\Http\Url::internal( 'app=core&module=online&controller=online', 'front', 'online' ), $where );
|
||||
$table->tableTemplate = array( \IPS\Theme::i()->getTemplate( 'online', 'core', 'front' ), 'onlineUsersTable' );
|
||||
@@ -57,20 +77,7 @@ class _online extends \IPS\Dispatcher\Controller
|
||||
$table->include = array( 'photo', 'member_name', 'location_lang', 'running_time', 'ip_address', 'login_type' );
|
||||
$table->limit = 30;
|
||||
$table->noSort = array( 'photo', 'location_lang' );
|
||||
|
||||
/* Joins */
|
||||
$table->joins = array(
|
||||
array(
|
||||
'select' => 'm.member_id',
|
||||
'from' => array( 'core_members', 'm' ),
|
||||
'where' => 'm.member_id=core_sessions.member_id'
|
||||
),
|
||||
array(
|
||||
'from' => 'core_groups',
|
||||
'where' => 'core_sessions.member_group=core_groups.g_id'
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
/* Custom parsers */
|
||||
$table->parsers = array(
|
||||
'location_lang' => function( $val, $row )
|
||||
@@ -99,10 +106,10 @@ class _online extends \IPS\Dispatcher\Controller
|
||||
);
|
||||
|
||||
$table->filters = array(
|
||||
'filter_loggedin' => 'm.member_id <> 0',
|
||||
'filter_loggedin' => 'core_sessions.member_id <> 0',
|
||||
);
|
||||
|
||||
foreach ( \IPS\Member\Group::groups() as $group )
|
||||
foreach ( \IPS\Member\Group::groups( TRUE, TRUE, TRUE ) as $group )
|
||||
{
|
||||
/* Hiding from online list? */
|
||||
if( $group->g_hide_online_list )
|
||||
@@ -117,11 +124,11 @@ class _online extends \IPS\Dispatcher\Controller
|
||||
|
||||
if( $group->g_id == \IPS\Settings::i()->guest_group )
|
||||
{
|
||||
$table->filters[ 'group_' . $group->g_id ] = 'm.member_id IS NULL';
|
||||
$table->filters[ 'group_' . $group->g_id ] = 'core_sessions.member_id IS NULL';
|
||||
}
|
||||
else
|
||||
{
|
||||
$table->filters[ 'group_' . $group->g_id ] = 'm.member_group_id=' . $group->g_id;
|
||||
$table->filters[ 'group_' . $group->g_id ] = 'core_sessions.member_group=' . $group->g_id;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Search
|
||||
* @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 18 Apr 2014
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -34,10 +34,19 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/streams.css' ) );
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/search.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()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_search.js', 'core' ) );
|
||||
\IPS\Output::i()->metaTags['robots'] = 'noindex'; // Tell search engines not to index search pages
|
||||
|
||||
|
||||
if( !\IPS\Settings::i()->tags_enabled and isset( \IPS\Request::i()->tags ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'page_doesnt_exist', '2C205/4', 404, '' );
|
||||
}
|
||||
|
||||
/* Get the form */
|
||||
$baseUrl = \IPS\Http\Url::internal( 'app=core&module=search&controller=search', 'front', 'search' );
|
||||
$form = $this->_form();
|
||||
@@ -73,6 +82,11 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'search' )->search( $this->_splitTermsForDisplay(), FALSE, FALSE, FALSE, $baseUrl, FALSE, $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'search' ), 'filters' ), $baseUrl, NULL ), 0, TRUE );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Number of member search results to retrieve
|
||||
*/
|
||||
protected $memberSearchResults = 24;
|
||||
|
||||
/**
|
||||
* Get Results
|
||||
@@ -81,6 +95,15 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function _results()
|
||||
{
|
||||
/* Make sure we are not doing anything nefarious like passing an array the the "q" parameter, which generates errors */
|
||||
foreach( array( 'q', 'type' ) AS $parameter )
|
||||
{
|
||||
if ( isset( \IPS\Request::i()->$parameter ) AND is_array( \IPS\Request::i()->$parameter ) )
|
||||
{
|
||||
\IPS\Request::i()->$parameter = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Init */
|
||||
$baseUrl = \IPS\Http\Url::internal( 'app=core&module=search&controller=search', 'front', 'search' );
|
||||
if( \IPS\Request::i()->q )
|
||||
@@ -103,13 +126,17 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
$baseUrl = $baseUrl->setQueryString( 'type', \IPS\Request::i()->type );
|
||||
if ( \IPS\Request::i()->q )
|
||||
{
|
||||
$where = array( array( 'LOWER(core_members.name) LIKE ?', '%' . mb_strtolower( \IPS\Request::i()->q ) . '%' ) );
|
||||
$where = array( array( 'LOWER(core_members.name) LIKE ?', '%' . mb_strtolower( trim( \IPS\Request::i()->q ) ) . '%' ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
$where = array( array( 'core_members.name<>?', '' ) );
|
||||
}
|
||||
|
||||
|
||||
if ( isset( \IPS\Request::i()->joinedDate ) and !isset( \IPS\Request::i()->start_after ) )
|
||||
{
|
||||
\IPS\Request::i()->start_after = \IPS\Request::i()->joinedDate;
|
||||
}
|
||||
if ( isset( \IPS\Request::i()->start_before ) or isset( \IPS\Request::i()->start_after ) )
|
||||
{
|
||||
foreach ( array( 'before', 'after' ) as $l )
|
||||
@@ -162,20 +189,29 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
/* Only exclude by group if the only value isn't __EMPTY **/
|
||||
if( !is_array( \IPS\Request::i()->group ) OR ( count( \IPS\Request::i()->group ) > 1 OR !isset( \IPS\Request::i()->group['__EMPTY'] ) ) )
|
||||
{
|
||||
$baseUrl = $baseUrl->setQueryString( 'group', \IPS\Request::i()->group );
|
||||
$where[] = \IPS\Db::i()->in( 'core_members.member_group_id', ( is_array( \IPS\Request::i()->group ) ) ? array_filter( array_keys( \IPS\Request::i()->group ), function( $val ){
|
||||
$groups = ( is_array( \IPS\Request::i()->group ) ) ? array_filter( array_keys( \IPS\Request::i()->group ), function( $val ){
|
||||
if( $val == '__EMPTY' )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} ) : explode( ',', \IPS\Request::i()->group ) );
|
||||
} ) : explode( ',', \IPS\Request::i()->group );
|
||||
|
||||
foreach( $groups as $_idx => $groupId )
|
||||
{
|
||||
if( \IPS\Member\Group::load( $groupId )->g_bitoptions['gbw_hide_group'] )
|
||||
{
|
||||
unset( $groups[ $_idx ] );
|
||||
}
|
||||
}
|
||||
$baseUrl = $baseUrl->setQueryString( 'group', \IPS\Request::i()->group );
|
||||
$where[] = \IPS\Db::i()->in( 'core_members.member_group_id', $groups );
|
||||
}
|
||||
}
|
||||
|
||||
/* Figure out member custom field filters */
|
||||
foreach ( \IPS\core\ProfileFields\Field::fields( array(), \IPS\core\ProfileFields\PROFILE ) as $group => $fields )
|
||||
foreach ( \IPS\core\ProfileFields\Field::fields( array(), \IPS\core\ProfileFields\Field::SEARCH ) as $group => $fields )
|
||||
{
|
||||
/* Fields */
|
||||
foreach ( $fields as $id => $field )
|
||||
@@ -193,13 +229,21 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
case 'IPS\Helpers\Form\Url':
|
||||
case 'IPS\Helpers\Form\Date':
|
||||
case 'IPS\Helpers\Form\Number':
|
||||
$fieldName = 'core_pfield_' . $id;
|
||||
|
||||
if( isset( \IPS\Request::i()->$fieldName ) )
|
||||
{
|
||||
$where[] = array( 'LOWER(core_pfields_content.field_' . $id . ') LIKE ?', '%' . mb_strtolower( \IPS\Request::i()->$fieldName ) . '%' );
|
||||
$baseUrl = $baseUrl->setQueryString( $fieldName, \IPS\Request::i()->$fieldName );
|
||||
}
|
||||
break;
|
||||
case 'IPS\Helpers\Form\Select':
|
||||
case 'IPS\Helpers\Form\Radio':
|
||||
$fieldName = 'core_pfield_' . $id;
|
||||
|
||||
if( isset( \IPS\Request::i()->$fieldName ) )
|
||||
{
|
||||
$where[] = array( 'LOWER(core_pfields_content.field_' . $id . ') LIKE ?', '%' . mb_strtolower( \IPS\Request::i()->$fieldName ) . '%' );
|
||||
$where[] = array( 'core_pfields_content.field_' . $id . ' = ?', mb_strtolower( \IPS\Request::i()->$fieldName ) );
|
||||
$baseUrl = $baseUrl->setQueryString( $fieldName, \IPS\Request::i()->$fieldName );
|
||||
}
|
||||
break;
|
||||
@@ -238,13 +282,13 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
$select = \IPS\Db::i()->select( 'COUNT(*)', 'core_members', $where );
|
||||
$select->join( 'core_pfields_content', 'core_pfields_content.member_id=core_members.member_id' );
|
||||
$count = $select->first();
|
||||
|
||||
$select = \IPS\Db::i()->select( 'core_members.*', 'core_members', $where, $order, array( ( $page - 1 ) * 25, 25 ) );
|
||||
|
||||
$select = \IPS\Db::i()->select( 'core_members.*', 'core_members', $where, $order, array( ( $page - 1 ) * $this->memberSearchResults, $this->memberSearchResults ) );
|
||||
$select->join( 'core_pfields_content', 'core_pfields_content.member_id=core_members.member_id' );
|
||||
|
||||
$results = new \IPS\Patterns\ActiveRecordIterator( $select, 'IPS\Member' );
|
||||
|
||||
$pagination = trim( \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $baseUrl, ceil( $count / 25 ), $page, 1 ) );
|
||||
$pagination = trim( \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $baseUrl, ceil( $count / $this->memberSearchResults ), $page, $this->memberSearchResults, TRUE, 'page', ( $count > \IPS\UPGRADE_MANUAL_THRESHOLD ? TRUE : FALSE ) ) );
|
||||
if ( !\IPS\Request::i()->q )
|
||||
{
|
||||
$title = \IPS\Member::loggedIn()->language()->addToStack( 'members' );
|
||||
@@ -288,6 +332,7 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
$query->filterByContent( array( \IPS\Content\Search\ContentFilter::init( $class )->onlyInItems( array( \IPS\Request::i()->item ) ) ) );
|
||||
$baseUrl = $baseUrl->setQueryString( 'item', intval( \IPS\Request::i()->item ) );
|
||||
$titleConditions[] = \IPS\Member::loggedIn()->language()->addToStack( 'search_blurb_in', FALSE, array( 'sprintf' => array( $item->mapped('title') ) ) );
|
||||
$baseUrl = $baseUrl->setQueryString( 'type', \IPS\Request::i()->type );
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
}
|
||||
@@ -298,11 +343,27 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
|
||||
if ( isset( \IPS\Request::i()->nodes ) )
|
||||
{
|
||||
$nodeClass = $types[ \IPS\Request::i()->type ]::$containerNodeClass;
|
||||
$node = $nodeClass::loadAndCheckPerms( \IPS\Request::i()->nodes );
|
||||
$filter->onlyInContainers( explode( ',', \IPS\Request::i()->nodes ) );
|
||||
$baseUrl = $baseUrl->setQueryString( 'nodes', \IPS\Request::i()->nodes );
|
||||
$titleConditions[] = \IPS\Member::loggedIn()->language()->addToStack( 'search_blurb_in', FALSE, array( 'sprintf' => array( $node->_title ) ) );
|
||||
|
||||
$nodes = array();
|
||||
$nodeClass = $types[ \IPS\Request::i()->type ]::$containerNodeClass;
|
||||
foreach ( explode( ',', \IPS\Request::i()->nodes ) as $id )
|
||||
{
|
||||
try
|
||||
{
|
||||
$nodes[] = $nodeClass::loadAndCheckPerms( $id )->_title;
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
}
|
||||
|
||||
if ( !$nodes )
|
||||
{
|
||||
\IPS\Output::i()->error( 'search_invalid_nodes', '2C205/5', 404, '' );
|
||||
}
|
||||
|
||||
$nodes = \IPS\Member::loggedIn()->language()->formatList( $nodes );
|
||||
$titleConditions[] = \IPS\Member::loggedIn()->language()->addToStack( 'search_blurb_in', FALSE, array( 'sprintf' => array( $nodes ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -362,7 +423,7 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$$l = NULL;
|
||||
$key = "{$l}Key";
|
||||
if ( isset( \IPS\Request::i()->$$key ) )
|
||||
if ( isset( \IPS\Request::i()->$$key ) AND \IPS\Request::i()->$$key != 'any' )
|
||||
{
|
||||
switch ( \IPS\Request::i()->$$key )
|
||||
{
|
||||
@@ -408,9 +469,15 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
/* Work out the title */
|
||||
if ( \IPS\Request::i()->tags )
|
||||
{
|
||||
/* @todo Remove when we fix \Http\Url as there are issues with urlencode/decoding */
|
||||
if ( ! \IPS\Settings::i()->htaccess_mod_rewrite )
|
||||
{
|
||||
\IPS\Request::i()->tags = urldecode( \IPS\Request::i()->tags );
|
||||
}
|
||||
|
||||
$tagList = array_map( function( $val )
|
||||
{
|
||||
return '\'' . htmlentities( $val, \IPS\HTMLENTITIES, 'UTF-8', FALSE ) . '\'';
|
||||
return '\'' . htmlentities( $val, \IPS\HTMLENTITIES | ENT_QUOTES, 'UTF-8', FALSE ) . '\'';
|
||||
}, explode( ',', \IPS\Request::i()->tags ) );
|
||||
}
|
||||
$title = '';
|
||||
@@ -458,28 +525,24 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/* Set Order */
|
||||
if ( isset( \IPS\Request::i()->sortby ) )
|
||||
if ( ! isset( \IPS\Request::i()->sortby ) )
|
||||
{
|
||||
switch( \IPS\Request::i()->sortby )
|
||||
{
|
||||
case 'newest':
|
||||
$query->setOrder( \IPS\Content\Search\Query::ORDER_NEWEST_CREATED );
|
||||
break;
|
||||
\IPS\Request::i()->sortby = $query->getDefaultSortMethod();
|
||||
}
|
||||
|
||||
switch( \IPS\Request::i()->sortby )
|
||||
{
|
||||
case 'newest':
|
||||
$query->setOrder( \IPS\Content\Search\Query::ORDER_NEWEST_CREATED );
|
||||
break;
|
||||
|
||||
case 'relevancy':
|
||||
$query->setOrder( \IPS\Content\Search\Query::ORDER_RELEVANCY );
|
||||
break;
|
||||
}
|
||||
|
||||
$baseUrl = $baseUrl->setQueryString( 'sortby', \IPS\Request::i()->sortby );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Default to relevancy which is a total score of relevancy + date + title weighted search */
|
||||
$query->setOrder( \IPS\Content\Search\Query::ORDER_RELEVANCY );
|
||||
$baseUrl = $baseUrl->setQueryString( 'sortby', 'relevancy' );
|
||||
case 'relevancy':
|
||||
$query->setOrder( \IPS\Content\Search\Query::ORDER_RELEVANCY );
|
||||
break;
|
||||
}
|
||||
|
||||
$baseUrl = $baseUrl->setQueryString( 'sortby', \IPS\Request::i()->sortby );
|
||||
|
||||
$flags = ( isset( \IPS\Request::i()->eitherTermsOrTags ) and \IPS\Request::i()->eitherTermsOrTags === 'and' ) ? \IPS\Content\Search\Query::TERM_AND_TAGS : \IPS\Content\Search\Query::TERM_OR_TAGS;
|
||||
|
||||
if ( isset( \IPS\Request::i()->search_and_or ) and \IPS\Request::i()->search_and_or === 'or' )
|
||||
@@ -498,23 +561,31 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
$results = $query->search(
|
||||
isset( \IPS\Request::i()->q ) ? ( \IPS\Request::i()->q ) : NULL,
|
||||
isset( \IPS\Request::i()->tags ) ? explode( ',', \IPS\Request::i()->tags ) : NULL,
|
||||
$flags
|
||||
$flags + \IPS\Content\Search\Query::TAGS_MATCH_ITEMS_ONLY
|
||||
);
|
||||
|
||||
/* Get pagination */
|
||||
$page = isset( \IPS\Request::i()->page ) ? intval( \IPS\Request::i()->page ) : 1;
|
||||
$count = $results->count( TRUE );
|
||||
$pages = ceil( $results->count( TRUE ) / $query->resultsToGet );
|
||||
|
||||
if( $page < 1 )
|
||||
if ( ! $count )
|
||||
{
|
||||
/* Enforce that we're on page 1 if there are no results to prevent page tampering */
|
||||
$page = 1;
|
||||
}
|
||||
else if( $count and ( $page < 1 or $page > $pages ) )
|
||||
{
|
||||
/* There's no point resetting the page at this point as the search query has been run and no results have been found */
|
||||
$_SESSION['lastSearch'] = 0;
|
||||
\IPS\Output::i()->redirect( $baseUrl->setQueryString( 'page', 1 ) );
|
||||
}
|
||||
|
||||
$pagination = trim( \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $baseUrl, ceil( $results->count( TRUE ) / $query->resultsToGet ), $page, $query->resultsToGet ) );
|
||||
$pagination = trim( \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $baseUrl, $pages, $page, $query->resultsToGet ) );
|
||||
|
||||
/* Display results */
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
$count = $results->count( TRUE );
|
||||
\IPS\Output::i()->json( array(
|
||||
'filters' => $this->_form()->customTemplate( array( \IPS\Theme::i()->getTemplate( 'search' ), 'filters' ), $baseUrl, $count ),
|
||||
'hints' => \IPS\Theme::i()->getTemplate( 'search' )->hints( $baseUrl, $count ),
|
||||
@@ -526,11 +597,10 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
else
|
||||
{
|
||||
$httpHeaders = array( 'Expires' => \IPS\DateTime::create()->add( new \DateInterval( 'PT3M' ) )->rfc1123() ,
|
||||
'Cache-Control' => "max-age=" . 30 * 60 . ", public" );
|
||||
'Cache-Control' => "max-age=" . 30 * 60 . ", private" );
|
||||
|
||||
\IPS\Output::i()->httpHeaders += $httpHeaders;
|
||||
|
||||
$count = $results->count( TRUE );
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('search_results_title');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'search' )->search( $this->_splitTermsForDisplay(), $title, $results, $pagination, $baseUrl, $types, $this->_form()->customTemplate( array( \IPS\Theme::i()->getTemplate( 'search' ), 'filters' ), $baseUrl, $count ), $count );
|
||||
}
|
||||
@@ -552,12 +622,34 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
$form->hiddenValues['item'] = \IPS\Request::i()->item;
|
||||
}
|
||||
|
||||
if ( isset( \IPS\Request::i()->sortby ) )
|
||||
{
|
||||
$form->hiddenValues['sortby'] = \IPS\Request::i()->sortby;
|
||||
}
|
||||
|
||||
if ( isset( \IPS\Request::i()->sortdirection ) )
|
||||
{
|
||||
$form->hiddenValues['sortdirection'] = \IPS\Request::i()->sortdirection;
|
||||
}
|
||||
|
||||
/* If we do a quick search the type is set to 'all' but we want it as '' for the form to work properly */
|
||||
if( isset( \IPS\Request::i()->type ) AND \IPS\Request::i()->type === 'all' )
|
||||
{
|
||||
\IPS\Request::i()->type = '';
|
||||
}
|
||||
|
||||
/* Set up some sensible defaults */
|
||||
if ( ! isset( \IPS\Request::i()->updated_after ) )
|
||||
{
|
||||
\IPS\Request::i()->updated_after = \IPS\Content\Search\Query::init()->getDefaultDateCutOff();
|
||||
}
|
||||
|
||||
/* Types */
|
||||
$types = array( '' => 'search_everything' );
|
||||
$contentTypes = $this->_contentTypes();
|
||||
$contentToggles = array();
|
||||
$typeFields = array();
|
||||
$typeFieldToggles = array( '' => array( 'search_min_views', 'search_min_reviews', 'search_min_comments' ) );
|
||||
$typeFieldToggles = array('' => array() );
|
||||
$haveCommentClass = FALSE;
|
||||
$haveReplyClass = FALSE;
|
||||
$haveReviewClass = FALSE;
|
||||
@@ -566,8 +658,8 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
'day' => 'last_24hr',
|
||||
'week' => 'last_week',
|
||||
'month' => 'last_month',
|
||||
'six_months' => 'six_months',
|
||||
'year' => 'year',
|
||||
'six_months' => 'last_six_months',
|
||||
'year' => 'last_year',
|
||||
'custom' => 'custom'
|
||||
);
|
||||
|
||||
@@ -578,7 +670,7 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Figure out member fields to set toggles */
|
||||
$memberToggles = array( 'joinedDate', 'core_members_group' );
|
||||
foreach ( \IPS\core\ProfileFields\Field::fields( array(), \IPS\core\ProfileFields\PROFILE ) as $group => $fields )
|
||||
foreach ( \IPS\core\ProfileFields\Field::fields( array(), \IPS\core\ProfileFields\Field::SEARCH ) as $group => $fields )
|
||||
{
|
||||
foreach ( $fields as $id => $field )
|
||||
{
|
||||
@@ -632,7 +724,7 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
/* Term */
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'q' ), NULL, 'search_tab_all' );
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'tags', \IPS\Request::i()->tags, FALSE, array( 'autocomplete' => array() ), NULL, NULL, NULL, 'tags' ), NULL, 'search_tab_content' );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'tags', \IPS\Request::i()->tags, FALSE, array( 'autocomplete' => TRUE ), NULL, NULL, NULL, 'tags' ), NULL, 'search_tab_content' );
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'eitherTermsOrTags', \IPS\Request::i()->eitherTermsOrTags, FALSE, array( 'options' => array( 'or' => 'termsortags_or_desc', 'and' => 'termsortags_and_desc' ) ), NULL, NULL, NULL, 'eitherTermsOrTags' ), NULL, 'search_tab_content' );
|
||||
|
||||
/* Author */
|
||||
@@ -647,16 +739,16 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
/* Other filters */
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'search_in', \IPS\Request::i()->search_in, FALSE, array( 'options' => array( 'all' => 'titles_and_body', 'titles' => 'titles_only' ) ), NULL, NULL, NULL, 'searchIn' ), NULL, 'search_tab_content' );
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'search_and_or', \IPS\Request::i()->search_and_or, FALSE, array( 'options' => array( 'and' => 'search_and', 'or' => 'search_or' ) ), NULL, NULL, NULL, 'andOr' ), NULL, 'search_tab_content' );
|
||||
|
||||
|
||||
/* Nodes */
|
||||
foreach ( $contentTypes as $k => $class )
|
||||
{
|
||||
if ( isset( $class::$containerNodeClass ) and isset( \IPS\Request::i()->type ) and \IPS\Request::i()->type === $k )
|
||||
if ( isset( $class::$containerNodeClass ) )
|
||||
{
|
||||
$nodeClass = $class::$containerNodeClass;
|
||||
$field = new \IPS\Helpers\Form\Node( 'nodes', ( isset( \IPS\Request::i()->nodes ) ) ? \IPS\Request::i()->nodes : NULL, FALSE, array( 'class' => $nodeClass, 'multiple' => TRUE, 'permissionCheck' => 'view', ), NULL, NULL, NULL, $k . '_node' );
|
||||
$field = new \IPS\Helpers\Form\Node( $k . '_node', ( isset( \IPS\Request::i()->nodes ) ) ? \IPS\Request::i()->nodes : NULL, FALSE, array( 'class' => $nodeClass, 'multiple' => TRUE, 'permissionCheck' => $nodeClass::searchableNodesPermission(), 'forceOwner' => FALSE ), NULL, NULL, NULL, $k . '_node' );
|
||||
$field->label = \IPS\Member::loggedIn()->language()->addToStack( $nodeClass::$nodeTitle );
|
||||
$form->add( $field, NULL, 'search_tab_content' );
|
||||
$form->add( $field, NULL, 'search_tab_nodes' );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -680,14 +772,15 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/* Member group and joined */
|
||||
$groups = \IPS\Member\Group::groups(TRUE, FALSE);
|
||||
$form->add(new \IPS\Helpers\Form\CheckboxSet('group', (isset(\IPS\Request::i()->group)) ? array_keys(\IPS\Request::i()->group) : array_keys( $groups ), FALSE, array('options' => $groups, 'parse' => 'normal'), NULL, NULL, NULL, 'core_members_group'), NULL, 'search_tab_member' );
|
||||
$groups = \IPS\Member\Group::groups( TRUE, FALSE, TRUE );
|
||||
|
||||
$form->add(new \IPS\Helpers\Form\CheckboxSet('group', ( isset( \IPS\Request::i()->group ) ) ? is_array( \IPS\Request::i()->group) ? array_keys( \IPS\Request::i()->group) : array( \IPS\Request::i()->group ) : array_keys( $groups ), FALSE, array('options' => $groups, 'parse' => 'normal'), NULL, NULL, NULL, 'core_members_group'), NULL, 'search_tab_member' );
|
||||
$form->add(new \IPS\Helpers\Form\Select('joinedDate', (isset(\IPS\Request::i()->start_before) or (isset(\IPS\Request::i()->start_after) and is_numeric(\IPS\Request::i()->start_after))) ? 'custom' : \IPS\Request::i()->start_after, FALSE, array('options' => $dateOptions, 'toggles' => array('custom' => array('elCustomDate_joinedDate'))), NULL, NULL, NULL, 'joinedDate'), NULL, 'search_tab_member' );
|
||||
$form->add(new \IPS\Helpers\Form\DateRange('joinedDateCustom', array('start' => (isset(\IPS\Request::i()->start_after) and is_numeric(\IPS\Request::i()->start_after)) ? \IPS\DateTime::ts(\IPS\Request::i()->start_after) : NULL, 'end' => isset(\IPS\Request::i()->start_before) ? \IPS\DateTime::ts(\IPS\Request::i()->start_before) : NULL)), NULL, 'search_tab_member' );
|
||||
|
||||
/* Profile fields for member searches */
|
||||
$memberFields = array();
|
||||
foreach ( \IPS\core\ProfileFields\Field::fields( array(), \IPS\core\ProfileFields\SEARCH ) as $group => $fields )
|
||||
foreach ( \IPS\core\ProfileFields\Field::fields( array(), \IPS\core\ProfileFields\Field::SEARCH ) as $group => $fields )
|
||||
{
|
||||
$fieldsToAdd = array();
|
||||
/* Fields */
|
||||
@@ -717,15 +810,18 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
$memberFields[] = 'core_pfield_' . $id;
|
||||
break;
|
||||
case 'IPS\Helpers\Form\Number':
|
||||
$helper = new \IPS\Helpers\Form\Number( 'core_pfield_' . $id, NULL, FALSE, array(), NULL, NULL, NULL, 'core_pfield_' . $id );
|
||||
$helper = new \IPS\Helpers\Form\Number( 'core_pfield_' . $id, -1, FALSE, array( 'unlimited' => -1, 'unlimitedLang' => 'member_number_anyvalue' ), NULL, NULL, NULL, 'core_pfield_' . $id );
|
||||
$memberFields[] = 'core_pfield_' . $id;
|
||||
break;
|
||||
case 'IPS\Helpers\Form\Select':
|
||||
case 'IPS\Helpers\Form\Radio':
|
||||
$options = array( '' => "" );
|
||||
foreach ( $field->options['options'] as $option )
|
||||
if( count( $field->options['options'] ) )
|
||||
{
|
||||
$options[ $option ] = $option;
|
||||
foreach ($field->options['options'] as $option)
|
||||
{
|
||||
$options[$option] = $option;
|
||||
}
|
||||
}
|
||||
|
||||
$helper = new \IPS\Helpers\Form\Select( 'core_pfield_' . $id, NULL, FALSE, array( 'options' => $options ), NULL, NULL, NULL, 'core_pfield_' . $id );
|
||||
@@ -871,7 +967,7 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
$types = array();
|
||||
foreach ( \IPS\Content::routedClasses( TRUE, FALSE, TRUE ) as $class )
|
||||
{
|
||||
if( is_subclass_of( $class, 'IPS\Content\Searchable' ) and $class::$includeInSiteSearch )
|
||||
if( is_subclass_of( $class, 'IPS\Content\Searchable' ) and $class::includeInSiteSearch() )
|
||||
{
|
||||
$key = mb_strtolower( str_replace( '\\', '_', mb_substr( $class, 4 ) ) );
|
||||
$types[ $key ] = $class;
|
||||
@@ -894,8 +990,9 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
|
||||
$words = preg_split("/[\s]*\\\"([^\\\"]+)\\\"[\s]*|[\s]*'([^']+)'[\s]*|[\s]+/", \IPS\Request::i()->q, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
|
||||
|
||||
foreach( $words as $idx => $word ){
|
||||
$words[ $idx ] = htmlentities( $word, \IPS\HTMLENTITIES, 'UTF-8', FALSE );
|
||||
foreach( $words as $idx => $word )
|
||||
{
|
||||
$words[ $idx ] = htmlentities( $word, \IPS\HTMLENTITIES | ENT_QUOTES, 'UTF-8', FALSE ); // ENT_QUOTES is because this will go in a HTML attribute (data-term="$value") so if you include a single quote in your search query, it can break
|
||||
}
|
||||
|
||||
return json_encode( $words );
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Print out sitemap
|
||||
* @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 30 Aug 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -34,7 +34,7 @@ class _sitemap extends \IPS\Content\Controller
|
||||
{
|
||||
try
|
||||
{
|
||||
$content = \IPS\Db::i()->select( 'data', 'core_sitemap', array( 'sitemap=?', \IPS\Request::i()->file ) )->first();
|
||||
$content = \IPS\Db::i()->select( 'data', 'core_sitemap', array( 'data IS NOT NULL AND sitemap=?', \IPS\Request::i()->file ) )->first();
|
||||
$content = str_replace( '<loc>{base_url}', '<loc>' . \IPS\Settings::i()->base_url, $content );
|
||||
|
||||
/* http://www.w3.org/TR/REC-xml/#charsets */
|
||||
@@ -50,7 +50,7 @@ class _sitemap extends \IPS\Content\Controller
|
||||
$sitemapUrl = \IPS\Http\Url::external( \IPS\Settings::i()->sitemap_url ? rtrim( \IPS\Settings::i()->sitemap_url, '/' ) : rtrim( \IPS\Settings::i()->base_url, '/' ) . '/sitemap.php' );
|
||||
|
||||
$content = \IPS\Xml\SimpleXML::create( 'sitemapindex', 'http://www.sitemaps.org/schemas/sitemap/0.9' );
|
||||
foreach ( \IPS\Db::i()->select( array( 'sitemap', 'updated' ), 'core_sitemap' ) as $sitemap )
|
||||
foreach ( \IPS\Db::i()->select( array( 'sitemap', 'updated' ), 'core_sitemap', array( 'data IS NOT NULL' ) ) as $sitemap )
|
||||
{
|
||||
$content->addChild( 'sitemap', array( 'loc' => $sitemapUrl->setQueryString( 'file', $sitemap['sitemap'] ), 'lastmod' => \IPS\DateTime::ts( $sitemap['updated'] )->format('c') ) );
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Staff directory
|
||||
* @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 19 Sep 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -30,7 +30,7 @@ class _directory extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
\IPS\Output::i()->breadcrumb['module'] = array( \IPS\Http\Url::internal( 'app=core&module=members&controller=directory', 'front', 'staffdirectory' ), \IPS\Member::loggedIn()->language()->addToStack('staff') );
|
||||
\IPS\Output::i()->breadcrumb['module'] = array( \IPS\Http\Url::internal( 'app=core&module=staffdirectory&controller=directory', 'front', 'staffdirectory' ), \IPS\Member::loggedIn()->language()->addToStack('staff') );
|
||||
|
||||
parent::execute();
|
||||
}
|
||||
@@ -82,8 +82,8 @@ class _directory extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'leader_custom_name', ( \IPS\Member::loggedIn()->language()->checkKeyExists("core_staff_directory_name_{$user->id}") ) ? \IPS\Member::loggedIn()->language()->addToStack("core_staff_directory_name_{$user->id}") : \IPS\Member::loggedIn()->name, FALSE ) );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'leader_custom_title', ( \IPS\Member::loggedIn()->language()->checkKeyExists("core_staff_directory_title_{$user->id}") ) ? \IPS\Member::loggedIn()->language()->addToStack("core_staff_directory_title_{$user->id}") : \IPS\Member::loggedIn()->member_title, FALSE ) );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'leader_custom_name', ( \IPS\Member::loggedIn()->language()->checkKeyExists("core_staff_directory_name_{$user->id}") ) ? \IPS\Member::loggedIn()->language()->get("core_staff_directory_name_{$user->id}") : \IPS\Member::loggedIn()->name, FALSE ) );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'leader_custom_title', ( \IPS\Member::loggedIn()->language()->checkKeyExists("core_staff_directory_title_{$user->id}") ) ? \IPS\Member::loggedIn()->language()->get("core_staff_directory_title_{$user->id}") : \IPS\Member::loggedIn()->member_title, FALSE ) );
|
||||
$form->add( new \IPS\Helpers\Form\Editor( 'leader_custom_bio', \IPS\Member::loggedIn()->language()->addToStack("core_staff_directory_bio_{$user->id}"), FALSE, array(
|
||||
'app' => 'core',
|
||||
'key' => 'Staffdirectory',
|
||||
@@ -101,7 +101,7 @@ class _directory extends \IPS\Dispatcher\Controller
|
||||
//$user->save();
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=members&controller=directory", 'front', 'staffdirectory' ), 'saved' );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=staffdirectory&controller=directory", 'front', 'staffdirectory' ), 'saved' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('leader_edit_mine');
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Status Updates Feed
|
||||
* @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 15 Aug 2014
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief AJAX actions
|
||||
* @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 04 Apr 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -26,7 +26,7 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
/**
|
||||
* Find Member
|
||||
*
|
||||
* @retun void
|
||||
* @return void
|
||||
*/
|
||||
public function findMember()
|
||||
{
|
||||
@@ -57,8 +57,8 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
$results[] = array(
|
||||
'id' => $member->member_id,
|
||||
'value' => $member->name,
|
||||
'name' => \IPS\Dispatcher::i()->controllerLocation == 'admin' ? $member->group['prefix'] . htmlspecialchars( $member->name, \IPS\HTMLENTITIES, 'UTF-8', FALSE ) . $member->group['suffix'] : htmlspecialchars( $member->name, \IPS\HTMLENTITIES, 'UTF-8', FALSE ),
|
||||
'extra' => \IPS\Dispatcher::i()->controllerLocation == 'admin' ? $member->email : $member->groupName,
|
||||
'name' => \IPS\Dispatcher::i()->controllerLocation == 'admin' ? $member->group['prefix'] . htmlspecialchars( $member->name, \IPS\HTMLENTITIES | ENT_QUOTES, 'UTF-8', FALSE ) . $member->group['suffix'] : htmlspecialchars( $member->name, \IPS\HTMLENTITIES | ENT_QUOTES, 'UTF-8', FALSE ),
|
||||
'extra' => \IPS\Dispatcher::i()->controllerLocation == 'admin' ? htmlspecialchars( $member->email, \IPS\HTMLENTITIES | ENT_QUOTES, 'UTF-8', FALSE ) : $member->groupName,
|
||||
'photo' => (string) $member->photo,
|
||||
);
|
||||
}
|
||||
@@ -83,6 +83,10 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$result = array( 'result' => 'fail', 'message' => \IPS\Member::loggedIn()->language()->addToStack('form_required') );
|
||||
}
|
||||
elseif ( mb_strlen( $name ) < \IPS\Settings::i()->min_user_name_length )
|
||||
{
|
||||
$result = array( 'result' => 'fail', 'message' => \IPS\Member::loggedIn()->language()->addToStack( 'form_minlength', FALSE, array( 'pluralize' => array( \IPS\Settings::i()->min_user_name_length ) ) ) );
|
||||
}
|
||||
elseif ( mb_strlen( $name ) > \IPS\Settings::i()->max_user_name_length )
|
||||
{
|
||||
$result = array( 'result' => 'fail', 'message' => \IPS\Member::loggedIn()->language()->addToStack( 'form_maxlength', FALSE, array( 'pluralize' => array( \IPS\Settings::i()->max_user_name_length ) ) ) );
|
||||
@@ -102,10 +106,12 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
if ( \IPS\Member::loggedIn()->isAdmin() )
|
||||
{
|
||||
$result = array( 'result' => 'fail', 'message' => \IPS\Member::loggedIn()->language()->addToStack('member_name_exists_admin', FALSE, array( 'sprintf' => array( $k ) ) ) );
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
$result = array( 'result' => 'fail', 'message' => \IPS\Member::loggedIn()->language()->addToStack('member_name_exists') );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -119,6 +125,7 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
if( preg_match( '/^' . str_replace( '\*', '.*', preg_quote( $bannedName, '/' ) ) . '$/i', $name ) )
|
||||
{
|
||||
$result = array( 'result' => 'fail', 'message' => \IPS\Member::loggedIn()->language()->addToStack('form_name_banned') );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,6 +174,19 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
/* Check it's not banned */
|
||||
if ( $result == array( 'result' => 'ok' ) )
|
||||
{
|
||||
foreach( \IPS\Db::i()->select( 'ban_content', 'core_banfilters', array("ban_type=?", 'email') ) as $bannedEmail )
|
||||
{
|
||||
if( preg_match( '/^' . str_replace( '\*', '.*', preg_quote( $bannedEmail, '/' ) ) . '$/i', $email ) )
|
||||
{
|
||||
$result = array( 'result' => 'fail', 'message' => \IPS\Member::loggedIn()->language()->addToStack('form_email_banned') );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->json( $result );
|
||||
}
|
||||
|
||||
@@ -204,19 +224,21 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
switch ( \IPS\Request::i()->time )
|
||||
{
|
||||
case 'week':
|
||||
$where[] = array( 'rep_date>?', \IPS\DateTime::create()->sub( new \DateInterval( 'P1W' ) )->getTimestamp() );
|
||||
$where[] = array( 'rep_date>' . \IPS\DateTime::create()->sub( new \DateInterval( 'P1W' ) )->getTimestamp() );
|
||||
$timeframe = 'week';
|
||||
break;
|
||||
case 'month':
|
||||
$where[] = array( 'rep_date>?', \IPS\DateTime::create()->sub( new \DateInterval( 'P1M' ) )->getTimestamp() );
|
||||
$where[] = array( 'rep_date>' . \IPS\DateTime::create()->sub( new \DateInterval( 'P1M' ) )->getTimestamp() );
|
||||
$timeframe = 'month';
|
||||
break;
|
||||
case 'year':
|
||||
$where[] = array( 'rep_date>?', \IPS\DateTime::create()->sub( new \DateInterval( 'P1Y' ) )->getTimestamp() );
|
||||
$where[] = array( 'rep_date>' . \IPS\DateTime::create()->sub( new \DateInterval( 'P1Y' ) )->getTimestamp() );
|
||||
$timeframe = 'year';
|
||||
break;
|
||||
}
|
||||
$topContributors = iterator_to_array( \IPS\Db::i()->select( 'core_reputation_index.member_received as member, SUM(rep_rating) as rep', 'core_reputation_index', $where, 'rep DESC', $limit, 'member' )->setKeyField('member')->setValueField('rep') );
|
||||
|
||||
$innerQuery = \IPS\Db::i()->select( 'core_reputation_index.member_received as member, SUM(rep_rating) as rep', 'core_reputation_index', $where, NULL, NULL, 'member' );
|
||||
$topContributors = iterator_to_array( \IPS\Db::i()->select( 'member, rep', array( $innerQuery, 'in' ), NULL, 'rep DESC', $limit )->setKeyField('member')->setValueField('rep') );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -237,6 +259,7 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'block_topContributors' );
|
||||
\IPS\Output::i()->output = $output;
|
||||
}
|
||||
}
|
||||
@@ -261,7 +284,7 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
/**
|
||||
* Instant Notifications
|
||||
*
|
||||
* @retun void
|
||||
* @return void
|
||||
*/
|
||||
public function instantNotifications()
|
||||
{
|
||||
@@ -272,7 +295,7 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the intitial counts */
|
||||
/* Get the initial counts */
|
||||
$return = array( 'notifications' => array( 'count' => \IPS\Member::loggedIn()->notification_cnt, 'data' => array() ), 'messages' => array( 'count' => \IPS\Member::loggedIn()->msg_count_new, 'data' => array() ) );
|
||||
|
||||
/* If there's new notifications, get the actual data */
|
||||
@@ -280,15 +303,29 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$notificationsDifference = $return['notifications']['count'] - \IPS\Request::i()->notifications;
|
||||
|
||||
/* Cap at 200 to prevent DOSing the server when there are like 1000+ notifications to send */
|
||||
if( $notificationsDifference > 200 )
|
||||
{
|
||||
$notificationsDifference = 200;
|
||||
}
|
||||
|
||||
foreach ( new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'core_notifications', array( 'member=? AND ( read_time IS NULL OR read_time<? )', \IPS\Member::loggedIn()->member_id, time() ), 'updated_time DESC', $notificationsDifference ), 'IPS\Notification\Inline' ) as $notification )
|
||||
{
|
||||
$data = $notification->getData();
|
||||
/* It is possible that the content has been removed after the iterator has started but before we fetch the data */
|
||||
try
|
||||
{
|
||||
$data = $notification->getData();
|
||||
}
|
||||
catch( \OutOfRangeException $e )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$return['notifications']['data'][] = array(
|
||||
'id' => $notification->id,
|
||||
'title' => $data['title'],
|
||||
'title' => htmlspecialchars( $data['title'], \IPS\HTMLENTITIES | ENT_QUOTES, 'UTF-8', FALSE ),
|
||||
'url' => (string) $data['url'],
|
||||
'content' => isset( $data['content'] ) ? $data['content'] : NULL,
|
||||
'content' => isset( $data['content'] ) ? htmlspecialchars( $data['content'], \IPS\HTMLENTITIES, 'UTF-8', FALSE ) : NULL,
|
||||
'date' => $notification->updated_time->getTimestamp(),
|
||||
'author_photo' => $data['author'] ? $data['author']->photo : NULL
|
||||
);
|
||||
@@ -309,7 +346,7 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
|
||||
$return['messages']['data'][] = array(
|
||||
'id' => $conversation->id,
|
||||
'title' => $conversation->title,
|
||||
'title' => htmlspecialchars( $conversation->title, \IPS\HTMLENTITIES | ENT_QUOTES, 'UTF-8', FALSE ),
|
||||
'url' => (string) $conversation->url()->setQueryString( 'latest', 1 ),
|
||||
'message' => $message->truncated(),
|
||||
'date' => $message->mapped('date'),
|
||||
@@ -322,4 +359,23 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
/* And return */
|
||||
\IPS\Output::i()->json( $return );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns score in json indicating the strength of a password
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function passwordStrength()
|
||||
{
|
||||
/* The value comes urlencoded so we need to decode so length is correct (and not using a percent-encoded value) */
|
||||
$password = urldecode( \IPS\Request::i()->input );
|
||||
|
||||
require_once \IPS\ROOT_PATH . "/system/3rd_party/phpass/phpass.php";
|
||||
|
||||
$phpass = new \PasswordStrength();
|
||||
|
||||
$response = array( 'result' => 'ok', 'score' => $phpass->classify( $password ), 'granular' => $phpass->calculate( $password ) );
|
||||
|
||||
\IPS\Output::i()->json( $response );
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Announcement
|
||||
* @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 09 Oct 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -46,6 +46,11 @@ class _announcement extends \IPS\Content\Controller
|
||||
{
|
||||
\IPS\Output::i()->error( 'announcement_missing', '2C199/1', 404, '' );
|
||||
}
|
||||
|
||||
if ( !$announcement->canView() )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error_no_perm', '2C199/2', 403, '' );
|
||||
}
|
||||
|
||||
/* Set Session Location */
|
||||
\IPS\Session::i()->setLocation( \IPS\Http\Url::internal( 'app=core&module=system&controller=announcement&id=' . $announcement->id, NULL, 'announcement', $announcement->seo_title ), array(), 'loc_viewing_announcement', array( $announcement->title => FALSE ) );
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief My Attachments Controller
|
||||
* @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 22 Jul 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -64,36 +64,6 @@ class _attachments extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('myAttachments')->template( (string) $table, \IPS\Db::i()->select( 'SUM(attach_filesize)', 'core_attachments', array( 'attach_member_id=?', \IPS\Member::loggedIn()->member_id ) )->first(), \IPS\Db::i()->select( 'COUNT(*)', 'core_attachments', array( 'attach_member_id=?', \IPS\Member::loggedIn()->member_id ) )->first() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function lookup()
|
||||
{
|
||||
/* Load and check permission */
|
||||
try
|
||||
{
|
||||
$attachment = \IPS\Db::i()->select( '*', 'core_attachments', array( 'attach_id=?', \IPS\Request::i()->id ) )->first();
|
||||
}
|
||||
catch ( \UnderflowException $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C229/6', 404, '' );
|
||||
}
|
||||
|
||||
/* Check it belongs to us */
|
||||
if ( $attachment['attach_member_id'] !== \IPS\Member::loggedIn()->member_id or !\IPS\Member::loggedIn()->group['gbw_delete_attachments'] )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C229/7', 403, '' );
|
||||
}
|
||||
|
||||
/* Display */
|
||||
\IPS\Output::i()->title = $attachment['attach_file'];
|
||||
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( 'app=core&module=system&controller=attachments', 'front', 'attachments' ), \IPS\Member::loggedIn()->language()->addToStack('my_attachments') );
|
||||
\IPS\Output::i()->breadcrumb[] = array( NULL, $attachment['attach_file'] );
|
||||
\IPS\Output::i()->output = $this->_getLocations( $attachment['attach_id'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete
|
||||
*
|
||||
@@ -103,6 +73,9 @@ class _attachments extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/* Security check */
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
/* Make sure the user confirmed the deletion */
|
||||
\IPS\Request::i()->confirmedDelete();
|
||||
|
||||
/* Load and check permission */
|
||||
try
|
||||
@@ -152,6 +125,5 @@ class _attachments extends \IPS\Dispatcher\Controller
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=attachments', 'front', 'attachments' ) );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief "Content" functions Controller
|
||||
* @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 29 Apr 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -44,10 +44,9 @@ class _content extends \IPS\Dispatcher\Controller
|
||||
|
||||
try
|
||||
{
|
||||
$item = $class::load( \IPS\Request::i()->content_id );
|
||||
$commentClass = $class::$commentClass;
|
||||
|
||||
$comment = $commentClass::load( \IPS\Request::i()->content_commentid );
|
||||
$item = $comment->item();
|
||||
}
|
||||
catch( \OutOfRangeException $ex )
|
||||
{
|
||||
@@ -55,7 +54,7 @@ class _content extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/* Make sure we have permission to see this */
|
||||
if ( ( $comment->item()->tid == $item->tid ) AND $item->canView() AND $comment->canView() )
|
||||
if ( $item->canView() AND $comment->canView() )
|
||||
{
|
||||
\IPS\Output::i()->redirect( $comment->url() );
|
||||
}
|
||||
@@ -64,5 +63,4 @@ class _content extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->error( 'node_error', '2S226/4', 404, '' );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Designer mode controller
|
||||
* @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 07 Aug 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Editor AJAX functions Controller
|
||||
* @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 29 Apr 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -23,6 +23,17 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
*/
|
||||
class _editor extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* Preview iframe
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function preview()
|
||||
{
|
||||
$output = \IPS\Theme::i()->getTemplate( 'editor', 'core', 'global' )->preview( \IPS\Request::i()->editor_id );
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->blankTemplate( $output ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Link Dialog
|
||||
*
|
||||
@@ -41,7 +52,7 @@ class _editor extends \IPS\Dispatcher\Controller
|
||||
protected function code()
|
||||
{
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'codemirror/codemirror.css', 'core', 'interface' ) );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'editor', 'core', 'global' )->code( \IPS\Request::i()->val, \IPS\Request::i()->editorId, md5( uniqid() ), \IPS\Request::i()->lang ?: 'html' );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'editor', 'core', 'global' )->code( \IPS\Request::i()->val, \IPS\Request::i()->editorId, md5( uniqid() ), \IPS\Request::i()->lang ?: '' );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,21 +64,23 @@ class _editor extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$maxImageDims = \IPS\Settings::i()->attachment_image_size ? explode( 'x', \IPS\Settings::i()->attachment_image_size ) : array( 1000, 750 );
|
||||
$maxWidth = ( \IPS\Request::i()->actualWidth < $maxImageDims[0] ) ? \IPS\Request::i()->actualWidth : $maxImageDims[0];
|
||||
$maxHeight = ( \IPS\Request::i()->actualHeight < $maxImageDims[1] ) ? \IPS\Request::i()->actualHeight : $maxImageDims[1];
|
||||
$ratio = round( \IPS\Request::i()->height / \IPS\Request::i()->width, 2 );
|
||||
$maxHeight = ( \IPS\Request::i()->actualHeight < $maxImageDims[1] ) ? \IPS\Request::i()->actualHeight : $maxImageDims[1];
|
||||
$ratioH = round( \IPS\Request::i()->height / \IPS\Request::i()->width, 2 );
|
||||
$ratioW = round( \IPS\Request::i()->width / \IPS\Request::i()->height, 2 );
|
||||
|
||||
if ( \IPS\Request::i()->width > $maxWidth )
|
||||
{
|
||||
\IPS\Request::i()->width = $maxWidth;
|
||||
\IPS\Request::i()->height = floor( \IPS\Request::i()->width * $ratio );
|
||||
\IPS\Request::i()->height = floor( \IPS\Request::i()->width * $ratioH );
|
||||
}
|
||||
|
||||
if ( \IPS\Request::i()->height > $maxHeight )
|
||||
{
|
||||
\IPS\Request::i()->height = $maxHeight;
|
||||
\IPS\Request::i()->width = floor( \IPS\Request::i()->height * $ratio );
|
||||
\IPS\Request::i()->width = floor( \IPS\Request::i()->height * $ratioW );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'editor', 'core', 'global' )->image( \IPS\Request::i()->editorId, \IPS\Request::i()->width, \IPS\Request::i()->height, $maxWidth, $maxHeight, \IPS\Request::i()->float, \IPS\Request::i()->link, $ratio );
|
||||
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'editor', 'core', 'global' )->image( \IPS\Request::i()->editorId, \IPS\Request::i()->width, \IPS\Request::i()->height, $maxWidth, $maxHeight, \IPS\Request::i()->float, \IPS\Request::i()->link, $ratioW, $ratioH, urldecode( \IPS\Request::i()->imageAlt ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,48 +90,87 @@ class _editor extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function validateLink()
|
||||
{
|
||||
/* CSRF check */
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
/* Have we recently checked and validated this link? */
|
||||
$cacheKey = md5( \IPS\Request::i()->url . (bool) \IPS\Request::i()->noEmbed . (bool) \IPS\Request::i()->image . \IPS\Member::loggedIn()->language()->id );
|
||||
try
|
||||
{
|
||||
$title = NULL;
|
||||
$isEmbed = FALSE;
|
||||
$url = \IPS\Request::i()->url;
|
||||
if ( !\IPS\Request::i()->noEmbed and !\IPS\Request::i()->image and $embed = \IPS\Text\Parser::embeddableMedia( $url ) )
|
||||
$cachedResult = \IPS\Data\Cache::i()->getWithExpire( $cacheKey, TRUE );
|
||||
|
||||
\IPS\Output::i()->json( $cachedResult );
|
||||
}
|
||||
catch( \OutOfRangeException $e ){}
|
||||
|
||||
/* Fetch the result and cache it, then return it */
|
||||
try
|
||||
{
|
||||
$title = NULL;
|
||||
$isEmbed = FALSE;
|
||||
$url = \IPS\Http\Url::createFromString( \IPS\Request::i()->url, TRUE, TRUE );
|
||||
$embed = NULL;
|
||||
$error = NULL;
|
||||
|
||||
if ( !\IPS\Request::i()->noEmbed )
|
||||
{
|
||||
$insert = $embed;
|
||||
$isEmbed = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
$response = \IPS\Http\Url::external( $url )->request()->get();
|
||||
if ( \IPS\Request::i()->image and isset( $response->httpHeaders['Content-Type'] ) and mb_substr( $response->httpHeaders['Content-Type'], 0, 6 ) === 'image/' )
|
||||
{
|
||||
$insert = "<img src='{$url}' class='ipsImage'>";
|
||||
}
|
||||
else
|
||||
try
|
||||
{
|
||||
if ( \IPS\Request::i()->image )
|
||||
{
|
||||
throw new \DomainException;
|
||||
}
|
||||
|
||||
if ( \IPS\Request::i()->title )
|
||||
{
|
||||
$title = \IPS\Request::i()->title;
|
||||
}
|
||||
elseif ( isset( $response->httpHeaders['Content-Type'] ) and mb_substr( $response->httpHeaders['Content-Type'], 0, 9 ) === 'text/html' and preg_match( '/<title>(.+)<\/title>/', $response, $matches ) and isset( $matches[1] ) )
|
||||
{
|
||||
$title = $matches[1];
|
||||
$embed = \IPS\Text\Parser::_imageEmbed( $url, FALSE, TRUE );
|
||||
}
|
||||
else
|
||||
{
|
||||
$title = $url;
|
||||
$embed = \IPS\Text\Parser::embeddableMedia( $url );
|
||||
}
|
||||
|
||||
$insert = "<a href='{$url}' ipsNoEmbed='true'>{$title}</a>";
|
||||
}
|
||||
catch( \UnexpectedValueException $e )
|
||||
{
|
||||
switch( $e->getMessage() )
|
||||
{
|
||||
case 'embed__fail_404':
|
||||
$error = \IPS\Member::loggedIn()->language()->addToStack( $e->getMessage(), FALSE, array( 'sprintf' => array( \IPS\Member::loggedIn()->language()->get( 'embed__fail_' . $e->getCode() ) ) ) );
|
||||
break;
|
||||
|
||||
case 'embed__fail_403':
|
||||
$error = \IPS\Member::loggedIn()->language()->addToStack( $e->getMessage(), FALSE, array( 'sprintf' => array( $url->data['host'], \IPS\Member::loggedIn()->language()->get( 'embed__fail_' . $e->getCode() ) ) ) );
|
||||
break;
|
||||
|
||||
case 'embed__fail_500':
|
||||
$error = \IPS\Member::loggedIn()->language()->addToStack( $e->getMessage(), FALSE, array( 'sprintf' => array( $url->data['host'] ) ) );
|
||||
break;
|
||||
|
||||
default:
|
||||
$error = \IPS\Member::loggedIn()->language()->addToStack( $e->getMessage() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch ( \Exception $e ){ }
|
||||
}
|
||||
|
||||
\IPS\Output::i()->json( array( 'preview' => trim( $insert ), 'title' => $title, 'embed' => $isEmbed ) );
|
||||
|
||||
if ( $embed OR $error )
|
||||
{
|
||||
$insert = $embed;
|
||||
$isEmbed = $error ? FALSE : TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
$title = \IPS\Request::i()->title ?: $url;
|
||||
$insert = "<a href='{$url}' ipsNoEmbed='true'>{$title}</a>";
|
||||
}
|
||||
|
||||
$result = array( 'preview' => trim( $insert ), 'title' => $title, 'embed' => $isEmbed, 'errorMessage' => $error ? \IPS\Member::loggedIn()->language()->addToStack( 'embed_failure_message', FALSE, array( 'sprintf' => array( $error ) ) ) : NULL );
|
||||
|
||||
if( $error )
|
||||
{
|
||||
\IPS\Member::loggedIn()->language()->parseOutputForDisplay( $result['errorMessage'] );
|
||||
\IPS\Log::debug( $url . "\n" . $result['errorMessage'], 'embed_failure' );
|
||||
}
|
||||
|
||||
\IPS\Data\Cache::i()->storeWithExpire( $cacheKey, $result, \IPS\DateTime::create()->add( new\DateInterval( 'PT10S' ) ), TRUE );
|
||||
|
||||
\IPS\Output::i()->json( $result );
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
@@ -184,13 +236,13 @@ class _editor extends \IPS\Dispatcher\Controller
|
||||
$mediaSources[] = $k;
|
||||
}
|
||||
}
|
||||
|
||||
/* Work out what tab we're on */
|
||||
if ( !\IPS\Request::i()->tab )
|
||||
{
|
||||
if( !count( $mediaSources ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C270/1', 403, '' );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'editor', 'core', 'global' )->myMedia( \IPS\Request::i()->editorId, $mediaSources, NULL, NULL, NULL );
|
||||
return;
|
||||
}
|
||||
|
||||
$sources = $mediaSources;
|
||||
@@ -268,9 +320,12 @@ class _editor extends \IPS\Dispatcher\Controller
|
||||
protected function mention()
|
||||
{
|
||||
$results = '';
|
||||
foreach ( \IPS\Db::i()->select( '*', 'core_members', array( "name LIKE CONCAT( ?, '%' )", mb_strtolower( \IPS\Request::i()->input ) ), 'name', 10 ) as $row )
|
||||
if ( mb_strlen( \IPS\Request::i()->input ) > 0 )
|
||||
{
|
||||
$results .= \IPS\Theme::i()->getTemplate( 'editor', 'core', 'global' )->mentionRow( \IPS\Member::constructFromData( $row ) );
|
||||
foreach ( \IPS\Db::i()->select( '*', 'core_members', array( "name LIKE CONCAT( ?, '%' )", mb_strtolower( \IPS\Request::i()->input ) ), 'name', 10 ) as $row )
|
||||
{
|
||||
$results .= \IPS\Theme::i()->getTemplate( 'editor', 'core', 'global' )->mentionRow( \IPS\Member::constructFromData( $row ) );
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->sendOutput( $results );
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Embed iframe display
|
||||
* @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 15 Sep 2014
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -29,7 +29,32 @@ class _embed extends \IPS\Content\Controller
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
{
|
||||
\IPS\Output::i()->sendOutput( \IPS\Text\Parser::embeddableMedia( \IPS\Request::i()->url, TRUE ), 200 );
|
||||
{
|
||||
/* Check cache */
|
||||
$cacheKey = 'embed_' . md5( \IPS\Request::i()->url );
|
||||
try
|
||||
{
|
||||
$return = \IPS\Data\Cache::i()->getWithExpire( $cacheKey, TRUE );
|
||||
}
|
||||
|
||||
/* Not in cache - fetch */
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
try
|
||||
{
|
||||
$return = \IPS\Text\Parser::embeddableMedia( \IPS\Http\Url::createFromString( \IPS\Request::i()->url, FALSE, TRUE ), TRUE );
|
||||
}
|
||||
catch( \UnexpectedValueException $e )
|
||||
{
|
||||
$return = '';
|
||||
}
|
||||
|
||||
/* And cache */
|
||||
\IPS\Data\Cache::i()->storeWithExpire( $cacheKey, $return, \IPS\DateTime::create()->add( new \DateInterval('P1D') ), TRUE );
|
||||
}
|
||||
|
||||
/* Output */
|
||||
$js = \IPS\Output::i()->js( 'js/embedHandler.js', 'core', 'interface' );
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core', 'front' )->embedExternal( $return, $js ), 200 );
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief My followed content
|
||||
* @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 16 Apr 2014
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -109,6 +109,11 @@ class _followed extends \IPS\Dispatcher\Controller
|
||||
else
|
||||
{
|
||||
/* Display */
|
||||
if ( \IPS\Theme::i()->settings['responsive'] )
|
||||
{
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/followedcontent_responsive.css' ) );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js('front_system.js', 'core' ) );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu_followed_content');
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Guidelines
|
||||
* @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 Sept 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Ignore Preferences
|
||||
* @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 20 Aug 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -106,7 +106,7 @@ class _ignore extends \IPS\Dispatcher\Controller
|
||||
/* Display */
|
||||
\IPS\Output::i()->breadcrumb[] = array( NULL, \IPS\Member::loggedIn()->language()->addToStack('ignored_users') );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('ignored_users');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->ignore( $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'system' ), 'ignoreForm' ) ), (string) $table );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->ignore( $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'system' ), 'ignoreForm' ) ), (string) $table, ( isset( \IPS\Request::i()->id ) ? \IPS\Request::i()->id : 0 ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,12 +120,13 @@ class _ignore extends \IPS\Dispatcher\Controller
|
||||
|
||||
try
|
||||
{
|
||||
$member = \IPS\Member::load( \IPS\Request::i()->name, 'name' );
|
||||
/* We have to html_entity_decode because the javascript code sends the encoded name here */
|
||||
$member = \IPS\Member::load( html_entity_decode( \IPS\Request::i()->name, ENT_QUOTES, 'UTF-8' ), 'name' );
|
||||
|
||||
/* If \IPS\Member::load() cannot find a member, it just creates a new guest object, never throwing the exception */
|
||||
if ( !$member->member_id )
|
||||
{
|
||||
throw new \OutOfRangeException( 'user_does_not_exist' );
|
||||
throw new \OutOfRangeException( 'cannot_ignore_no_user' );
|
||||
}
|
||||
|
||||
if ( $member->member_id == \IPS\Member::loggedIn()->member_id )
|
||||
@@ -133,7 +134,7 @@ class _ignore extends \IPS\Dispatcher\Controller
|
||||
throw new \InvalidArgumentException( 'cannot_ignore_self' );
|
||||
}
|
||||
|
||||
if ( $member->group['gbw_cannot_be_ignored'] )
|
||||
if ( !$member->canBeIgnored() )
|
||||
{
|
||||
throw new \InvalidArgumentException( 'cannot_ignore_that_member' );
|
||||
}
|
||||
@@ -153,11 +154,7 @@ class _ignore extends \IPS\Dispatcher\Controller
|
||||
|
||||
\IPS\Output::i()->json( $data );
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
\IPS\Output::i()->json( $e->getMessage(), 404 );
|
||||
}
|
||||
catch( \InvalidArgumentException $e )
|
||||
catch( \Exception $e )
|
||||
{
|
||||
\IPS\Output::i()->json( array( 'error' => \IPS\Member::loggedIn()->language()->addToStack( $e->getMessage() ) ), 403 );
|
||||
}
|
||||
@@ -177,7 +174,7 @@ class _ignore extends \IPS\Dispatcher\Controller
|
||||
/* If \IPS\Member::load() cannot find a member, it just creates a new guest object, never throwing the exception */
|
||||
if ( !$member->member_id )
|
||||
{
|
||||
throw new \OutOfRangeException( 'user_does_not_exist' );
|
||||
throw new \OutOfRangeException( 'cannot_ignore_no_user' );
|
||||
}
|
||||
|
||||
if ( $member->member_id == \IPS\Member::loggedIn()->member_id )
|
||||
@@ -185,7 +182,7 @@ class _ignore extends \IPS\Dispatcher\Controller
|
||||
throw new \InvalidArgumentException( 'cannot_ignore_self' );
|
||||
}
|
||||
|
||||
if ( $member->group['gbw_cannot_be_ignored'] )
|
||||
if ( !$member->canBeIgnored() )
|
||||
{
|
||||
throw new \InvalidArgumentException( 'cannot_ignore_that_member' );
|
||||
}
|
||||
@@ -229,11 +226,7 @@ class _ignore extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('add_ignored_user');
|
||||
\IPS\Output::i()->output = $form->customTemplate( array( \IPS\Theme::i()->getTemplate( 'system' ), 'ignoreEditForm' ) );
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
\IPS\Output::i()->json( $e->getMessage(), 404 );
|
||||
}
|
||||
catch( \InvalidArgumentException $e )
|
||||
catch( \Exception $e )
|
||||
{
|
||||
\IPS\Output::i()->json( \IPS\Member::loggedIn()->language()->addToStack( $e->getMessage() ), 403 );
|
||||
}
|
||||
@@ -248,6 +241,9 @@ class _ignore extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
/* Make sure the user confirmed the deletion */
|
||||
\IPS\Request::i()->confirmedDelete();
|
||||
|
||||
try
|
||||
{
|
||||
$member = \IPS\Member::load( \IPS\Request::i()->id );
|
||||
@@ -283,6 +279,8 @@ class _ignore extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function ignoreType()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
try
|
||||
{
|
||||
if ( !in_array( \IPS\Request::i()->type, \IPS\core\Ignore::types() ) )
|
||||
@@ -294,7 +292,7 @@ class _ignore extends \IPS\Dispatcher\Controller
|
||||
|
||||
if ( !$member->member_id )
|
||||
{
|
||||
throw new \OutOfRangeException( 'user_does_not_exist' );
|
||||
throw new \OutOfRangeException( 'cannot_ignore_no_user' );
|
||||
}
|
||||
|
||||
if ( $member->member_id == \IPS\Member::loggedIn()->member_id )
|
||||
@@ -302,7 +300,7 @@ class _ignore extends \IPS\Dispatcher\Controller
|
||||
throw new \InvalidArgumentException( 'cannot_ignore_self' );
|
||||
}
|
||||
|
||||
if ( $member->group['gbw_cannot_be_ignored'] )
|
||||
if ( !$member->canBeIgnored() )
|
||||
{
|
||||
throw new \InvalidArgumentException( 'cannot_ignore_that_member' );
|
||||
}
|
||||
@@ -337,18 +335,8 @@ class _ignore extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=system&controller=ignore", 'front', 'ignore' ), 'ignore_adjusted' );
|
||||
}
|
||||
}
|
||||
catch( \OutOfRangeException $e )
|
||||
{
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->json( array( 'error' => 'user_does_not_exist' ), 404 );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->error( 'user_does_not_exist', '2C146/3', 404, '' );
|
||||
}
|
||||
}
|
||||
catch( \InvalidArgumentException $e )
|
||||
|
||||
catch( \Exception $e )
|
||||
{
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Language Changer
|
||||
* @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 17 Dec 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Login
|
||||
* @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 7 Jun 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -46,29 +46,13 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
$login = new \IPS\Login( \IPS\Http\Url::internal( "app=core&module=system&controller=login", 'front', 'login', NULL, \IPS\Settings::i()->logins_over_https ) );
|
||||
|
||||
/* Process */
|
||||
$error = isset( \IPS\Request::i()->_err ) ? \IPS\Request::i()->_err : NULL;
|
||||
$error = isset( \IPS\Request::i()->_err ) && \IPS\Member::loggedIn()->language()->checkKeyExists( \IPS\Request::i()->_err ) ? \IPS\Request::i()->_err : NULL;
|
||||
try
|
||||
{
|
||||
$member = $login->authenticate();
|
||||
if ( $member !== NULL )
|
||||
{
|
||||
$this->_doLogin( $member, $login->flags['signin_anonymous'], $login->flags['remember_me'] );
|
||||
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
$response = array( 'status' => 'success' );
|
||||
|
||||
if( !empty( \IPS\Request::i()->ref ) )
|
||||
{
|
||||
$response['redirect'] = \IPS\Request::i()->ref;
|
||||
}
|
||||
|
||||
\IPS\Output::i()->json( $response );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Login::getDestination()->setQueryString( '_fromLogin', 1 ) );
|
||||
}
|
||||
$this->_doLogin( $member, $login->flags['signin_anonymous'], $login->flags['remember_me'], \IPS\Login::getDestination() );
|
||||
}
|
||||
}
|
||||
catch ( \IPS\Login\Exception $e )
|
||||
@@ -78,7 +62,12 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
$e->member = $e->member->member_id;
|
||||
$_SESSION['linkAccounts'] = json_encode( $e );
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=login&do=link', 'front', 'login' ) );
|
||||
$linkUrl = \IPS\Http\Url::internal( 'app=core&module=system&controller=login&do=link', 'front', 'login' );
|
||||
if ( isset( \IPS\Request::i()->ref ) )
|
||||
{
|
||||
$linkUrl = $linkUrl->setQueryString( 'ref', \IPS\Request::i()->ref );
|
||||
}
|
||||
\IPS\Output::i()->redirect( $linkUrl );
|
||||
}
|
||||
|
||||
$error = $e->getMessage();
|
||||
@@ -105,25 +94,43 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
/**
|
||||
* Process the login
|
||||
*
|
||||
* @param \IPS\Member $member The member
|
||||
* @param bool $anonymous If the login is anonymous
|
||||
* @param bool $rememberMe If the "remember me" checkbox was checked
|
||||
* @param \IPS\Member $member The member
|
||||
* @param bool $anonymous If the login is anonymous
|
||||
* @param bool $rememberMe If the "remember me" checkbox was checked
|
||||
* @param \IPS\Http\Url $destination Where to redirect to
|
||||
* @param bool $bypass2FA If true, will not perform 2FA check
|
||||
* @return void
|
||||
*/
|
||||
protected function _doLogin( $member, $anonymous=FALSE, $rememberMe=TRUE )
|
||||
protected function _doLogin( $member, $anonymous=FALSE, $rememberMe=TRUE, $destination=NULL, $bypass2FA=FALSE )
|
||||
{
|
||||
/* Get destination */
|
||||
if ( !$destination )
|
||||
{
|
||||
$destination = \IPS\Http\Url::internal( '' );
|
||||
}
|
||||
|
||||
/* Do we need to do 2FA? */
|
||||
if ( !$bypass2FA and $output = \IPS\MFA\MFAHandler::accessToArea( 'core', 'AuthenticateFront', \IPS\Http\Url::internal( '' ), $member ) )
|
||||
{
|
||||
$_SESSION['processing2FA'] = array( 'memberId' => $member->member_id, 'anonymous' => $anonymous, 'remember' => $rememberMe, 'destination' => (string) $destination );
|
||||
\IPS\Output::i()->redirect( $destination->setQueryString( '_mfaLogin', 1 ) );
|
||||
}
|
||||
|
||||
/* Set anonymous cookie */
|
||||
if ( $anonymous and !\IPS\Settings::i()->disable_anonymous )
|
||||
{
|
||||
\IPS\Session::i()->setAnon();
|
||||
\IPS\Request::i()->setCookie( 'anon_login', 1 );
|
||||
}
|
||||
|
||||
/* Log in */
|
||||
\IPS\Session::i()->setMember( $member );
|
||||
|
||||
/* Set remember me cookie */
|
||||
if ( $rememberMe )
|
||||
{
|
||||
$expire = new \IPS\DateTime;
|
||||
$expire->add( new \DateInterval( 'P7D' ) );
|
||||
$expire->add( new \DateInterval( 'P3M' ) );
|
||||
\IPS\Request::i()->setCookie( 'member_id', $member->member_id, $expire );
|
||||
\IPS\Request::i()->setCookie( 'pass_hash', $member->member_login_key, $expire );
|
||||
|
||||
@@ -133,7 +140,65 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
/* Member sync */
|
||||
$member->memberSync( 'onLogin', array( \IPS\Login::getDestination() ) );
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( $destination->setQueryString( '_fromLogin', 1 ), '', 303 );
|
||||
}
|
||||
|
||||
/**
|
||||
* MFA
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function mfa()
|
||||
{
|
||||
/* Have we logged in? */
|
||||
$member = NULL;
|
||||
if ( isset( $_SESSION['processing2FA'] ) )
|
||||
{
|
||||
$member = \IPS\Member::load( $_SESSION['processing2FA']['memberId'] );
|
||||
}
|
||||
if ( !$member->member_id )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login' ) );
|
||||
}
|
||||
|
||||
/* Where do we want to go? */
|
||||
$destination = NULL;
|
||||
try
|
||||
{
|
||||
$destination = \IPS\Http\Url::createFromString( $_SESSION['processing2FA']['destination'] );
|
||||
}
|
||||
catch ( \Exception $e ) { }
|
||||
|
||||
/* Have we already done 2FA? */
|
||||
$output = \IPS\MFA\MFAHandler::accessToArea( 'core', 'AuthenticateFront', \IPS\Http\Url::internal( 'app=core&module=system&controller=login&do=mfa', 'front', 'login' ), $member );
|
||||
if ( !$output )
|
||||
{
|
||||
$this->_doLogin( $member, $_SESSION['processing2FA']['anonymous'], $_SESSION['processing2FA']['remember'], $destination, TRUE );
|
||||
}
|
||||
|
||||
/* Nope, just send us where we want to go not logged in */
|
||||
$qs = array( '_mfaLogin' => 1 );
|
||||
if ( isset( \IPS\Request::i()->_mfa ) )
|
||||
{
|
||||
$qs['_mfa'] = \IPS\Request::i()->_mfa;
|
||||
if ( isset( \IPS\Request::i()->_mfaMethod ) )
|
||||
{
|
||||
$qs['_mfaMethod'] = \IPS\Request::i()->_mfaMethod;
|
||||
}
|
||||
}
|
||||
elseif ( isset( \IPS\Request::i()->mfa_auth ) )
|
||||
{
|
||||
$qs['mfa_auth'] = \IPS\Request::i()->mfa_auth;
|
||||
}
|
||||
elseif ( isset( \IPS\Request::i()->mfa_setup ) )
|
||||
{
|
||||
$qs['mfa_setup'] = \IPS\Request::i()->mfa_setup;
|
||||
}
|
||||
\IPS\Output::i()->redirect( $destination->setQueryString( $qs ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -156,7 +221,11 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form( 'link_accounts', 'login' );
|
||||
$form->addDummy( 'email_address', isset( $details['email'] ) ? $details['email'] : $member->email );
|
||||
if ( isset( \IPS\Request::i()->ref ) )
|
||||
{
|
||||
$form->hiddenValues['ref'] = \IPS\Request::i()->ref;
|
||||
}
|
||||
$form->addDummy( 'email_address', htmlspecialchars( isset( $details['email'] ) ? $details['email'] : $member->email, \IPS\HTMLENTITIES, 'UTF-8', FALSE ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'password', NULL, TRUE, array( 'validateFor' => $member ) ) );
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
@@ -166,9 +235,21 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
$class::link( $member, $details['details'] );
|
||||
|
||||
unset( $_SESSION['linkAccounts'] );
|
||||
$this->_doLogin( $member );
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( '' ) );
|
||||
$destination = NULL;
|
||||
if ( isset( \IPS\Request::i()->ref ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$ref = \IPS\Http\Url::createFromString( base64_decode( \IPS\Request::i()->ref ) );
|
||||
if ( $ref instanceof \IPS\Http\Url\Internal )
|
||||
{
|
||||
$destination = $ref;
|
||||
}
|
||||
}
|
||||
catch ( \Exception $e ) { }
|
||||
}
|
||||
$this->_doLogin( $member, FALSE, TRUE, $destination );
|
||||
}
|
||||
catch ( \IPS\Login\Exception $e )
|
||||
{
|
||||
@@ -191,22 +272,10 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
\IPS\Request::i()->setCookie( 'member_id', NULL );
|
||||
\IPS\Request::i()->setCookie( 'pass_hash', NULL );
|
||||
\IPS\Request::i()->setCookie( 'anon_login', NULL );
|
||||
|
||||
foreach( \IPS\Request::i()->cookie as $name => $value )
|
||||
{
|
||||
if( mb_strpos( $name, "ipbforumpass_" ) !== FALSE )
|
||||
{
|
||||
\IPS\Request::i()->setCookie( $name, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
if( !empty( $_SERVER['HTTP_REFERER'] ) )
|
||||
{
|
||||
$referrer = new \IPS\Http\Url( $_SERVER['HTTP_REFERER'] );
|
||||
$redirectUrl = ( $referrer->isInternal and isset( $referrer->queryString['do'] ) and $referrer->queryString['do'] != 'validating' ) ? $referrer : \IPS\Http\Url::internal('');
|
||||
$referrer = \IPS\Http\Url::createFromString( $_SERVER['HTTP_REFERER'] );
|
||||
$redirectUrl = ( $referrer instanceof \IPS\Http\Url\Internal and ( !isset( $referrer->queryString['do'] ) or $referrer->queryString['do'] != 'validating' ) ) ? $referrer : \IPS\Http\Url::internal('');
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -226,6 +295,28 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->redirect( $redirectUrl );
|
||||
}
|
||||
|
||||
\IPS\Request::i()->setCookie( 'member_id', NULL );
|
||||
\IPS\Request::i()->setCookie( 'pass_hash', NULL );
|
||||
\IPS\Request::i()->setCookie( 'anon_login', NULL );
|
||||
|
||||
foreach( \IPS\Request::i()->cookie as $name => $value )
|
||||
{
|
||||
if( mb_strpos( $name, "ipbforumpass_" ) !== FALSE )
|
||||
{
|
||||
\IPS\Request::i()->setCookie( $name, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset session global parameters */
|
||||
$_SESSION = array();
|
||||
|
||||
/* We have to explicitly reset the session cookie
|
||||
@link http://php.net/manual/en/function.session-destroy.php */
|
||||
$params = session_get_cookie_params();
|
||||
|
||||
setcookie( session_name(), '', time() - 42000, $params["path"], $params["domain"], $params["secure"], $params["httponly"] );
|
||||
|
||||
/* Then destroy the session itself */
|
||||
session_destroy();
|
||||
|
||||
/* Login handler callback */
|
||||
@@ -268,7 +359,7 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Do it */
|
||||
$_SESSION['logged_in_from'] = array( 'id' => $admin->member_id, 'name' => $admin->name );
|
||||
$unique_id = md5( uniqid() );
|
||||
$unique_id = \IPS\Login::generateRandomString();
|
||||
$_SESSION['logged_in_as_key'] = $unique_id;
|
||||
\IPS\Data\Store::i()->$unique_id = $member->member_id;
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Lost Password
|
||||
* @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 26 Aug 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -32,7 +32,7 @@ class _lostpass extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/* Build the form */
|
||||
$form = new \IPS\Helpers\Form( "lostpass", 'request_password' );
|
||||
$form->add( new \IPS\Helpers\Form\Email( 'email_address', NULL, TRUE, array(), function( $val ){
|
||||
$form->add( new \IPS\Helpers\Form\Email( 'email_address', NULL, TRUE, array( 'bypassProfanity' => TRUE ), function( $val ){
|
||||
|
||||
/* Check email exists */
|
||||
$member = \IPS\Member::load( $val, 'email' );
|
||||
@@ -51,30 +51,52 @@ class _lostpass extends \IPS\Dispatcher\Controller
|
||||
/* Load the member */
|
||||
$member = \IPS\Member::load( $values['email_address'], 'email' );
|
||||
|
||||
/* Make a validation key */
|
||||
$vid = md5( $member->members_pass_hash . uniqid( mt_rand(), TRUE ) );
|
||||
|
||||
/* Get rid of old entries for this member */
|
||||
\IPS\DB::i()->delete( 'core_validating', array( 'member_id=? AND lost_pass=1', $member->member_id ) );
|
||||
|
||||
/* Update the DB for this member. */
|
||||
$validating = array(
|
||||
'vid' => $vid,
|
||||
'member_id' => $member->member_id,
|
||||
'entry_date' => time(),
|
||||
'lost_pass' => 1,
|
||||
'ip_address' => $member->ip_address,
|
||||
);
|
||||
/* If we have an existing validation record, we can just reuse it */
|
||||
$sendEmail = TRUE;
|
||||
try
|
||||
{
|
||||
$existing = \IPS\Db::i()->select( array( 'vid', 'email_sent' ), 'core_validating', array( 'member_id=? AND lost_pass=1', $member->member_id ) )->first();
|
||||
$vid = $existing['vid'];
|
||||
|
||||
\IPS\Db::i()->insert( 'core_validating', $validating );
|
||||
|
||||
/* If we sent a lost password email within the last 15 minutes, don't send another one otherwise someone could be a nuisence */
|
||||
if ( $existing['email_sent'] and $existing['email_sent'] > ( time() - 900 ) )
|
||||
{
|
||||
$sendEmail = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Db::i()->update( 'core_validating', array( 'email_sent' => time() ), array( 'vid=?', $vid ) );
|
||||
}
|
||||
}
|
||||
catch ( \UnderflowException $e )
|
||||
{
|
||||
$vid = md5( $member->members_pass_hash . \IPS\Login::generateRandomString() );
|
||||
|
||||
\IPS\Db::i()->insert( 'core_validating', array(
|
||||
'vid' => $vid,
|
||||
'member_id' => $member->member_id,
|
||||
'entry_date' => time(),
|
||||
'lost_pass' => 1,
|
||||
'ip_address' => $member->ip_address,
|
||||
'email_sent' => time(),
|
||||
) );
|
||||
}
|
||||
|
||||
/* Send email */
|
||||
\IPS\Email::buildFromTemplate( 'core', 'lost_password_init', array( $member, $vid ) )->send( $member );
|
||||
if ( $sendEmail )
|
||||
{
|
||||
\IPS\Email::buildFromTemplate( 'core', 'lost_password_init', array( $member, $vid ), \IPS\Email::TYPE_TRANSACTIONAL )->send( $member );
|
||||
$message = "lost_pass_confirm";
|
||||
}
|
||||
else
|
||||
{
|
||||
$message = "lost_pass_too_soon";
|
||||
}
|
||||
|
||||
/* Show confirmation page with further instructions */
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->lostPassConfirm();
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->lostPassConfirm( $message );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -102,32 +124,33 @@ class _lostpass extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Show form for new password */
|
||||
$form = new \IPS\Helpers\Form( "resetpass", 'save' );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'password', NULL, TRUE, array() ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'password', NULL, TRUE, array( 'showMeter' => \IPS\Settings::i()->password_strength_meter ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'password_confirm', NULL, TRUE, array( 'confirm' => 'password' ) ) );
|
||||
|
||||
/* Set new password */
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
/* Get the member */
|
||||
$member = \IPS\Member::load( $record['member_id'] );
|
||||
|
||||
$member->members_pass_salt = $member->generateSalt();
|
||||
$member->members_pass_hash = $member->encryptedPassword( $values['password'] );
|
||||
|
||||
/* Reset the failed logins storage - we don't need to save because the login handler will do that for us later */
|
||||
$member->failed_logins = array();
|
||||
$member->save();
|
||||
|
||||
/* Now reset the member's password */
|
||||
foreach ( \IPS\Login::handlers( TRUE ) as $handler )
|
||||
{
|
||||
/* We cannot update our password in some login handlers, that's ok */
|
||||
try
|
||||
{
|
||||
$handler->changePassword( $member, $values['password'] );
|
||||
}
|
||||
catch( \BadMethodCallException $e ){}
|
||||
}
|
||||
|
||||
/* Delete validating record and log in */
|
||||
\IPS\Db::i()->delete( 'core_validating', array( 'member_id=? AND lost_pass=1', $member->member_id ) );
|
||||
|
||||
/* If the member doesn't have any other validating rows validate them */
|
||||
try
|
||||
{
|
||||
$record = \IPS\Db::i()->select( '*', 'core_validating', array( 'member_id=?', $member->member_id ) )->first();
|
||||
}
|
||||
catch ( \UnderflowException $e )
|
||||
{
|
||||
$member->validate();
|
||||
}
|
||||
|
||||
/* Log in and redirect */
|
||||
\IPS\Session::i()->setMember( $member );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( '' ) );
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Mark site as read
|
||||
* @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 19 May 2014
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Live meta tag editor
|
||||
* @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 4 Sept 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -50,8 +50,8 @@ class _metatags extends \IPS\Dispatcher\Controller
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
/* Delete any existing database entries, as we are about to re-insert */
|
||||
\IPS\DB::i()->delete( 'core_seo_meta', array( 'meta_url=?', \IPS\Request::i()->meta_url ) );
|
||||
\IPS\DB::i()->delete( 'core_seo_meta', array( 'meta_url=?', trim( \IPS\Request::i()->meta_url, '/' ) ) );
|
||||
\IPS\Db::i()->delete( 'core_seo_meta', array( 'meta_url=?', \IPS\Request::i()->meta_url ) );
|
||||
\IPS\Db::i()->delete( 'core_seo_meta', array( 'meta_url=?', trim( \IPS\Request::i()->meta_url, '/' ) ) );
|
||||
|
||||
/* Start save array */
|
||||
$save = array(
|
||||
@@ -75,7 +75,7 @@ class _metatags extends \IPS\Dispatcher\Controller
|
||||
|
||||
$save['meta_tags'] = json_encode( $_tags );
|
||||
|
||||
\IPS\DB::i()->insert( 'core_seo_meta', $save );
|
||||
\IPS\Db::i()->insert( 'core_seo_meta', $save );
|
||||
unset( \IPS\Data\Store::i()->metaTags );
|
||||
|
||||
/* Send back to the page */
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Moderation
|
||||
* @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 23 Jul 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -33,12 +33,23 @@ class _moderation extends \IPS\Dispatcher\Controller
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
$member = \IPS\Member::load( \IPS\Request::i()->id );
|
||||
|
||||
$redirectTarget = ( \IPS\Request::i()->referrer ) ? \IPS\Http\Url::createFromString( urldecode( \IPS\Request::i()->referrer ), TRUE ) : $member->url();
|
||||
|
||||
if ( $member->member_id and $member->member_id != \IPS\Member::loggedIn()->member_id and \IPS\Member::loggedIn()->modPermission('can_flag_as_spammer') and !$member->modPermission() and !$member->isAdmin() )
|
||||
{
|
||||
if ( \IPS\Request::i()->s )
|
||||
{
|
||||
$member->flagAsSpammer();
|
||||
\IPS\Session::i()->modLog( 'modlog__spammer_flagged', array( $member->name => FALSE ) );
|
||||
|
||||
$actions = explode( ',', \IPS\Settings::i()->spm_option );
|
||||
|
||||
/* Redirect to the users profile if we're deleting the content to avoid that the moderator sees a 404 error message */
|
||||
if ( in_array( 'delete', $actions ) )
|
||||
{
|
||||
$redirectTarget = $member->url();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -47,6 +58,6 @@ class _moderation extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( ( \IPS\Request::i()->referrer ) ? new \IPS\Http\Url( urldecode( \IPS\Request::i()->referrer ), TRUE ) : $member->url(), ( \IPS\Request::i()->s ) ? 'account_flagged' : 'account_unflagged');
|
||||
\IPS\Output::i()->redirect( $redirectTarget, ( \IPS\Request::i()->s ) ? 'account_flagged' : 'account_unflagged');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Notification Settings Controller
|
||||
* @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 27 Aug 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -57,28 +57,6 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
\IPS\Output::i()->json( array( 'data' => \IPS\Theme::i()->getTemplate( 'system' )->notificationsAjax( $notifications ) ) );
|
||||
}
|
||||
elseif ( isset( \IPS\Request::i()->format ) and \IPS\Request::i()->format === 'rss' )
|
||||
{
|
||||
$document = \IPS\Xml\Rss::newDocument( $urlObject, \IPS\Member::loggedIn()->language()->get('notifications'), sprintf( \IPS\Member::loggedIn()->language()->get( 'notifications_rss_desc' ), \IPS\Member::loggedIn()->name, \IPS\Settings::i()->board_name ) );
|
||||
|
||||
if ( count( $table->getRows() ) )
|
||||
{
|
||||
foreach ( $table->getRows() as $notification )
|
||||
{
|
||||
\IPS\Member::loggedIn()->language()->parseOutputForDisplay( $notification['data']['title'] );
|
||||
|
||||
if( isset( $notification['data']['content'] ) )
|
||||
{
|
||||
\IPS\Member::loggedIn()->language()->parseOutputForDisplay( $notification['data']['content'] );
|
||||
}
|
||||
|
||||
$document->addItem( $notification['data']['title'], $notification['data']['url'], isset( $notification['data']['content'] ) ? $notification['data']['content'] : NULL, $notification['notification']->updated_time, $notification['notification']->id );
|
||||
}
|
||||
}
|
||||
|
||||
/* @note application/rss+xml is not a registered IANA mime-type so we need to stick with text/xml for RSS */
|
||||
\IPS\Output::i()->sendOutput( $document->asXML(), 200, 'text/xml' );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('notifications');
|
||||
@@ -113,7 +91,8 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'auto_track_type', \IPS\Member::loggedIn()->auto_follow['method'] ?: 'immediate', FALSE, array( 'options' => array(
|
||||
'immediate' => \IPS\Member::loggedIn()->language()->addToStack('follow_type_immediate'),
|
||||
'daily' => \IPS\Member::loggedIn()->language()->addToStack('follow_type_daily'),
|
||||
'weekly' => \IPS\Member::loggedIn()->language()->addToStack('follow_type_weekly')
|
||||
'weekly' => \IPS\Member::loggedIn()->language()->addToStack('follow_type_weekly'),
|
||||
'none' => \IPS\Member::loggedIn()->language()->addToStack('follow_type_none')
|
||||
) ), NULL, NULL, NULL, 'auto_track_type' ) );
|
||||
/* Changed in 4.1: since email_notifications_once is new, combined show_pm_popup in and made a checkbox set for better organization */
|
||||
$notificationPrefValues = array();
|
||||
@@ -457,9 +436,12 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
$output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'system', 'core' ) ), 'followForm' ) );
|
||||
|
||||
/* @see http://community.invisionpower.com/4bugtrack/follow-button-adds-meta-title-and-link-tags-r3209/ */
|
||||
if( \IPS\Request::i()->isAjax() ){
|
||||
if( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->sendOutput( $output, 200, 'text/html', \IPS\Output::i()->httpHeaders );
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->output = $output;
|
||||
}
|
||||
}
|
||||
@@ -591,21 +573,21 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
$thing = $class::loadAndCheckPerms( \IPS\Request::i()->follow_id );
|
||||
$followers = $thing->followers( $class::FOLLOW_PUBLIC, array( 'none', 'immediate', 'daily', 'weekly' ), NULL, array( ( $thisPage - 1 ) * $perPage, $perPage ), 'name' );
|
||||
$anonymous = $thing->followers( $class::FOLLOW_ANONYMOUS )->count( TRUE );
|
||||
$title = $thing->name;
|
||||
$title = $thing->mapped('title');
|
||||
}
|
||||
else
|
||||
{
|
||||
$thing = $class::load( \IPS\Request::i()->follow_id );
|
||||
$followers = $thing->followers( $class::FOLLOW_PUBLIC, array( 'none', 'immediate', 'daily', 'weekly' ), NULL, array( ( $thisPage - 1 ) * $perPage, $perPage ), 'name' );
|
||||
$anonymous = $thing->followers( $class::FOLLOW_ANONYMOUS )->count( TRUE );
|
||||
$title = $thing->mapped('title');
|
||||
$title = $thing->name;
|
||||
}
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C154/6', 404, '' );
|
||||
}
|
||||
|
||||
|
||||
/* Display */
|
||||
if ( \IPS\Request::i()->isAjax() and isset( \IPS\Request::i()->_infScroll ) )
|
||||
{
|
||||
@@ -614,12 +596,14 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
else
|
||||
{
|
||||
$url = \IPS\Http\Url::internal( "app=core&module=system§ion=notifications&do=followers&follow_app=". \IPS\Request::i()->follow_app ."&follow_area=". \IPS\Request::i()->follow_area ."&follow_id=" . \IPS\Request::i()->follow_id . "&_infScroll=1" );
|
||||
$removeAllUrl = \IPS\Http\Url::internal( "app=core&module=system§ion=notifications&do=removeFollowers&follow_app=". \IPS\Request::i()->follow_app ."&follow_area=". \IPS\Request::i()->follow_area ."&follow_id=" . \IPS\Request::i()->follow_id )->csrf();
|
||||
|
||||
$pagination = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $url, ceil( $followers->count( TRUE ) / $perPage ), $thisPage, $perPage, FALSE, 'followerPage' );
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('item_followers', FALSE, array( 'sprintf' => array( $title ) ) );
|
||||
\IPS\Output::i()->breadcrumb[] = array( $thing->url(), $title );
|
||||
\IPS\Output::i()->breadcrumb[] = array( NULL, \IPS\Member::loggedIn()->language()->addToStack('who_follows_this') );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->followers( $url, $pagination, $followers, $anonymous );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->followers( $url, $pagination, $followers, $anonymous, $removeAllUrl );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -675,23 +659,42 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
if ( isset( \IPS\Request::i()->button_type ) && \IPS\Request::i()->button_type === 'search' )
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'profile' )->memberSearchFollowButton( \IPS\Request::i()->follow_app, \IPS\Request::i()->follow_area, \IPS\Request::i()->follow_id, $count );
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'profile' )->memberSearchFollowButton( \IPS\Request::i()->follow_app, \IPS\Request::i()->follow_area, \IPS\Request::i()->follow_id, $count ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'profile' )->memberFollowButton( \IPS\Request::i()->follow_app, \IPS\Request::i()->follow_area, \IPS\Request::i()->follow_id, $count );
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'profile' )->memberFollowButton( \IPS\Request::i()->follow_app, \IPS\Request::i()->follow_area, \IPS\Request::i()->follow_id, $count ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( \IPS\Request::i()->button_type == 'manage' )
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->manageFollowButton( \IPS\Request::i()->follow_app, \IPS\Request::i()->follow_area, \IPS\Request::i()->follow_id );
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'system' )->manageFollowButton( \IPS\Request::i()->follow_app, \IPS\Request::i()->follow_area, \IPS\Request::i()->follow_id ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global' )->followButton( \IPS\Request::i()->follow_app, \IPS\Request::i()->follow_area, \IPS\Request::i()->follow_id, $count );
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global' )->followButton( \IPS\Request::i()->follow_app, \IPS\Request::i()->follow_area, \IPS\Request::i()->follow_id, $count ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all followers
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function removeFollowers()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
if ( !\IPS\Member::loggedIn()->modPermission('can_remove_followers') )
|
||||
{
|
||||
\IPS\Output::i()->error( 'cant_remove_followers', '2C154/A', 403, 'cant_remove_followers_admin' );
|
||||
}
|
||||
|
||||
\IPS\Db::i()->delete( 'core_follow', array( 'follow_app=? AND follow_area=? AND follow_rel_id=?', \IPS\Request::i()->follow_app, \IPS\Request::i()->follow_area, \IPS\Request::i()->follow_id ) );
|
||||
|
||||
\IPS\Output::i()->redirect( ( !empty( $_SERVER['HTTP_REFERER'] ) ) ? \IPS\Http\Url::createFromString( $_SERVER['HTTP_REFERER'] ) : \IPS\Http\Url::internal( '' ), 'followers_removed' );
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief A deliberately empty controller intended for use by plugins which need to add small actions
|
||||
* @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 09 Aug 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Poll View Voters Controller
|
||||
* @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 13 Jan 2014
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Privacy Policy
|
||||
* @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 28 Jun 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief External redirector with key checks
|
||||
* @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 12 Jun 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -24,31 +24,61 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
class _redirect extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* Redirect the request appropriately
|
||||
* Handle munged links
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
{
|
||||
/* First check the key to make sure this actually came from HTMLPurifier */
|
||||
if ( \IPS\Request::i()->key == hash_hmac( "sha256", \IPS\Request::i()->url, md5( \IPS\Settings::i()->sql_pass . \IPS\Settings::i()->board_url . \IPS\Settings::i()->sql_database ) ) )
|
||||
if ( \IPS\Login::compareHashes( hash_hmac( "sha256", \IPS\Request::i()->url, \IPS\Settings::i()->site_secret_key ), (string) \IPS\Request::i()->key ) )
|
||||
{
|
||||
/* Is it a resource? (image, etc.) */
|
||||
/* Construct the URL */
|
||||
$url = \IPS\Http\Url::external( \IPS\Request::i()->url );
|
||||
|
||||
/* If it's a resource (image, etc.), we pull the actual contents to prevent the referrer being exposed (which is an issue in the ACP where the session ID is private) */
|
||||
if ( \IPS\Request::i()->resource )
|
||||
{
|
||||
/* If it's a resource, redirect without a message. Browsers should follow a location header for resources such as image fine. */
|
||||
/* Note that this scenario is hit if we have <img src='munged url' /> */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::external( \IPS\Request::i()->url ) );
|
||||
/* Except if it's internal or localhost, we can't make a HTTP request to it because doing that would potentially allow access to secured resources because the server
|
||||
thinks the request is internal. We don't need to worry about about things on this domain getting access to the referrer anyway */
|
||||
if ( $url->isLocalhost() )
|
||||
{
|
||||
\IPS\Output::i()->redirect( $url, NULL, 303 );
|
||||
}
|
||||
/* For everything else, pull the contents... */
|
||||
else
|
||||
{
|
||||
/* It can't be protocol relative */
|
||||
if ( !$url->data['scheme'] )
|
||||
{
|
||||
$url = \IPS\Http\Url::external( 'http:' . \IPS\Request::i()->url );
|
||||
}
|
||||
|
||||
/* Get the contents */
|
||||
try
|
||||
{
|
||||
$response = \IPS\Http\Url::external( $url )->request( \IPS\DEFAULT_REQUEST_TIMEOUT )->get();
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('') );
|
||||
}
|
||||
|
||||
/* Send output - we only want to pass along the content and content type. We can't allow the response
|
||||
to perform a redirect (which would cause the referrer to be exposed) and we don't want to pass
|
||||
along any of their headers which could include setting cookies, etc. */
|
||||
\IPS\Output::i()->sendOutput( $response->content, $response->httpResponseCode == 200 ? 200 : 404, isset( $response->httpHeaders['Content-Type'] ) ? $response->httpHeaders['Content-Type'] : 'unknown/unknown' );
|
||||
}
|
||||
}
|
||||
/* For everything else, we'll do a 303 redirect */
|
||||
else
|
||||
{
|
||||
/* Regular URL? Show a redirect page. */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::external( \IPS\Request::i()->url ), \IPS\Member::loggedIn()->language()->addToStack('external_redirect'), 303, TRUE );
|
||||
\IPS\Output::i()->redirect( $url, \IPS\Member::loggedIn()->language()->addToStack('external_redirect'), 303, TRUE );
|
||||
}
|
||||
}
|
||||
/* If it doesn't validate, send the user to the index page */
|
||||
else
|
||||
{
|
||||
/* Key did not validate, send the user to the index page */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('') );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Register
|
||||
* @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 3 July 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -60,15 +60,23 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
|
||||
if( isset( $_SESSION['coppa_user'] ) )
|
||||
{
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('reg_awaiting_validation');
|
||||
return \IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->notCoppaValidated();
|
||||
if ( \IPS\Settings::i()->minimum_age > 0 )
|
||||
{
|
||||
$message = \IPS\Member::loggedIn()->language()->addToStack( 'register_denied_age', FALSE, array( 'sprintf' => array( \IPS\Settings::i()->minimum_age ) ) );
|
||||
\IPS\Output::i()->error( $message, '2C223/7', 403, '' );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('reg_awaiting_validation');
|
||||
return \IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->notCoppaValidated();
|
||||
}
|
||||
}
|
||||
|
||||
/* Set up the step array */
|
||||
$steps = array();
|
||||
|
||||
/* If coppa is enabled we need to add a birthday verification */
|
||||
if ( \IPS\Settings::i()->use_coppa )
|
||||
if ( \IPS\Settings::i()->use_coppa OR \IPS\Settings::i()->minimum_age > 0 )
|
||||
{
|
||||
$steps['coppa'] = function( $data )
|
||||
{
|
||||
@@ -78,7 +86,16 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
|
||||
if( $values = $form->values() )
|
||||
{
|
||||
if( ( $values['bday']->diff( \IPS\DateTime::create() )->y < 13 ) )
|
||||
/* Did we pass the minimum age requirement? */
|
||||
if ( \IPS\Settings::i()->minimum_age > 0 AND $values['bday']->diff( \IPS\DateTime::create() )->y < \IPS\Settings::i()->minimum_age )
|
||||
{
|
||||
$_SESSION['coppa_user'] = TRUE;
|
||||
|
||||
$message = \IPS\Member::loggedIn()->language()->addToStack( 'register_denied_age', FALSE, array( 'sprintf' => array( \IPS\Settings::i()->minimum_age ) ) );
|
||||
\IPS\Output::i()->error( $message, '2C223/8', 403, '' );
|
||||
}
|
||||
/* We did, but we should check normal COPPA too */
|
||||
else if( ( $values['bday']->diff( \IPS\DateTime::create() )->y < 13 ) )
|
||||
{
|
||||
$_SESSION['coppa_user'] = TRUE;
|
||||
return \IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->notCoppaValidated();
|
||||
@@ -100,16 +117,18 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
/* Handle submissions */
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
/* Create Member */
|
||||
$member = \IPS\core\modules\front\system\register::_createMember( $values );
|
||||
|
||||
/* Custom Fields */
|
||||
$profileFields = array();
|
||||
|
||||
foreach ( \IPS\core\ProfileFields\Field::fields( array(), \IPS\core\ProfileFields\REG ) as $group => $fields )
|
||||
foreach ( \IPS\core\ProfileFields\Field::fields( array(), \IPS\core\ProfileFields\Field::REG ) as $group => $fields )
|
||||
{
|
||||
foreach ( $fields as $id => $field )
|
||||
{
|
||||
if( $field->required and ( $values[ $field->name ] === NULL or !isset( $values[ $field->name ] ) ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'reg_required_fields', '1C223/5', 403, '' );
|
||||
}
|
||||
|
||||
$profileFields[ "field_{$id}" ] = $field::stringValue( $values[ $field->name ] );
|
||||
|
||||
if ( $fields instanceof \IPS\Helpers\Form\Editor )
|
||||
@@ -118,33 +137,46 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
}
|
||||
\IPS\Db::i()->replace( 'core_pfields_content', array_merge( array( 'member_id' => $member->member_id ), $profileFields ) );
|
||||
|
||||
/* Email - We don't want to send if the new member is banned or we're not using email validation */
|
||||
if( \IPS\Settings::i()->reg_auth_type != 'none' AND \IPS\Settings::i()->reg_auth_type != 'admin' AND !$member->members_bitoptions['bw_is_spammer'] )
|
||||
if ( \IPS\Settings::i()->security_questions_enabled and ( \IPS\Settings::i()->security_questions_prompt === 'register' or ( \IPS\Settings::i()->security_questions_prompt === 'optional' and !$values['security_questions_optout_title'] ) ) )
|
||||
{
|
||||
\IPS\Email::buildFromTemplate( 'core', 'registration_validate', array( $member, \IPS\Db::i()->select( 'vid', 'core_validating', array( 'member_id=?', $member->member_id ) )->first() ) )->send( $member );
|
||||
$answers = array();
|
||||
foreach ( $values as $k => $v )
|
||||
{
|
||||
if ( preg_match( '/^security_question_q_(\d+)$/', $k, $matches ) )
|
||||
{
|
||||
if ( isset( $answers[ $v ] ) )
|
||||
{
|
||||
$form->error = \IPS\Member::loggedIn()->language()->addToStack( 'security_questions_unique', FALSE, array( 'pluralize' => array( \IPS\Settings::i()->security_questions_number ?: 3 ) ) );
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
$answers[ $v ] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Notify the incoming mail address except if they're a spammer */
|
||||
if( \IPS\Settings::i()->new_reg_notify && !$member->members_bitoptions['bw_is_spammer'] )
|
||||
if ( !$form->error )
|
||||
{
|
||||
\IPS\Email::buildFromTemplate( 'core', 'registration_notify', array( $member, $profileFields ) )->send( \IPS\Settings::i()->email_in );
|
||||
}
|
||||
|
||||
/* Log them in */
|
||||
\IPS\Session::i()->setMember( $member );
|
||||
|
||||
$redirectUrl = \IPS\Login::getRegistrationDestination( $member );
|
||||
|
||||
/* Redirect */
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->json( array( 'redirect' => (string) $redirectUrl ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->redirect( $redirectUrl );
|
||||
/* Create Member */
|
||||
$member = \IPS\core\modules\front\system\register::_createMember( $values, $profileFields );
|
||||
|
||||
/* Log them in */
|
||||
\IPS\Session::i()->setMember( $member );
|
||||
|
||||
$redirectUrl = \IPS\Login::getRegistrationDestination( $member );
|
||||
|
||||
/* Redirect */
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->json( array( 'redirect' => (string) $redirectUrl ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->redirect( $redirectUrl );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,12 +200,12 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
/* Build the form */
|
||||
$form = new \IPS\Helpers\Form( 'form', 'register_button', NULL, array( 'data-controller' => 'core.front.system.register') );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'username', NULL, TRUE, array( 'accountUsername' => TRUE ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Email( 'email_address', NULL, TRUE, array( 'accountEmail' => TRUE, 'maxLength' => 150 ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'password', NULL, TRUE, array() ) );
|
||||
$form->add( new \IPS\Helpers\Form\Email( 'email_address', NULL, TRUE, array( 'accountEmail' => TRUE, 'maxLength' => 150, 'bypassProfanity' => TRUE ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'password', NULL, TRUE, array( 'showMeter' => \IPS\Settings::i()->password_strength_meter, 'checkStrength' => TRUE ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'password_confirm', NULL, TRUE, array( 'confirm' => 'password' ) ) );
|
||||
|
||||
/* Profile fields */
|
||||
foreach ( \IPS\core\ProfileFields\Field::fields( array(), \IPS\core\ProfileFields\REG ) as $group => $fields )
|
||||
foreach ( \IPS\core\ProfileFields\Field::fields( array(), \IPS\core\ProfileFields\Field::REG ) as $group => $fields )
|
||||
{
|
||||
foreach ( $fields as $field )
|
||||
{
|
||||
@@ -189,6 +221,54 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
catch ( \UnderflowException $e ) {}
|
||||
|
||||
/* Security Questions */
|
||||
if ( \IPS\Settings::i()->security_questions_enabled and in_array( \IPS\Settings::i()->security_questions_prompt, array( 'register', 'optional' ) ) )
|
||||
{
|
||||
$numberOfQuestions = \IPS\Settings::i()->security_questions_number ?: 3;
|
||||
$securityQuestions = array();
|
||||
foreach ( \IPS\MFA\SecurityQuestions\Question::roots() as $securityQuestion )
|
||||
{
|
||||
$securityQuestions[ $securityQuestion->id ] = $securityQuestion->_title;
|
||||
}
|
||||
|
||||
$form->addMessage( \IPS\Member::loggedIn()->language()->addToStack('security_questions_setup_blurb', FALSE, array( 'pluralize' => array( $numberOfQuestions ) ) ) );
|
||||
if ( \IPS\Settings::i()->security_questions_prompt === 'optional' )
|
||||
{
|
||||
$securityOptoutToggles = array();
|
||||
foreach ( range( 1, min( $numberOfQuestions, count( $securityQuestions ) ) ) as $i )
|
||||
{
|
||||
$securityOptoutToggles[] = 'security_question_q_' . $i;
|
||||
$securityOptoutToggles[] = 'security_question_a_' . $i;
|
||||
}
|
||||
|
||||
$optOutCheckbox = new \IPS\Helpers\Form\Checkbox( 'security_questions_optout_title', FALSE, FALSE, array( 'togglesOff' => $securityOptoutToggles ) );
|
||||
if ( \IPS\Member::loggedIn()->language()->checkKeyExists('security_questions_opt_out_warning_value') )
|
||||
{
|
||||
$optOutCheckbox->description = \IPS\Member::loggedIn()->language()->addToStack('security_questions_opt_out_warning_value');
|
||||
}
|
||||
$form->add( $optOutCheckbox );
|
||||
}
|
||||
foreach ( range( 1, min( $numberOfQuestions, count( $securityQuestions ) ) ) as $i )
|
||||
{
|
||||
$securityValidation = function( $val ) {
|
||||
if ( !$val and ( \IPS\Settings::i()->security_questions_prompt === 'register' or !isset( \IPS\Request::i()->security_questions_optout_title_checkbox ) ) )
|
||||
{
|
||||
throw new \DomainException('form_required');
|
||||
}
|
||||
};
|
||||
|
||||
$questionField = new \IPS\Helpers\Form\Select( 'security_question_q_' . $i, NULL, FALSE, array( 'options' => $securityQuestions ), $securityValidation, NULL, NULL, 'security_question_q_' . $i );
|
||||
$questionField->label = \IPS\Member::loggedIn()->language()->addToStack('security_question_q');
|
||||
|
||||
$answerField = new \IPS\Helpers\Form\Text( 'security_question_a_' . $i, NULL, NULL, array(), $securityValidation, NULL, NULL, 'security_question_a_' . $i );
|
||||
$answerField->label = \IPS\Member::loggedIn()->language()->addToStack('security_question_a');
|
||||
|
||||
$form->add( $questionField );
|
||||
$form->add( $answerField );
|
||||
}
|
||||
$form->addSeparator();
|
||||
}
|
||||
|
||||
/* Random Q&A */
|
||||
if( $question )
|
||||
{
|
||||
@@ -280,10 +360,11 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
/**
|
||||
* Create Member
|
||||
*
|
||||
* @param array $values Values from form
|
||||
* @param array $values Values from form
|
||||
* @param array $profileFields Profile field values from registration
|
||||
* @return \IPS\Member
|
||||
*/
|
||||
public static function _createMember( $values )
|
||||
public static function _createMember( $values, $profileFields )
|
||||
{
|
||||
/* Create */
|
||||
$member = new \IPS\Member;
|
||||
@@ -303,15 +384,50 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->error( 'spam_denied_account', '2S129/1', 403, '' );
|
||||
}
|
||||
}
|
||||
|
||||
/* Will we be validating? */
|
||||
if ( \IPS\Settings::i()->reg_auth_type != 'none' )
|
||||
|
||||
/* Save */
|
||||
$member->save();
|
||||
|
||||
/* Security Questions */
|
||||
if ( \IPS\Settings::i()->security_questions_enabled and in_array( \IPS\Settings::i()->security_questions_prompt, array( 'register', 'optional' ) ) )
|
||||
{
|
||||
$member->members_bitoptions['validating'] = TRUE;
|
||||
if ( $values['security_questions_optout_title'] )
|
||||
{
|
||||
$member->members_bitoptions['security_questions_opt_out'] = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
$answers = array();
|
||||
|
||||
foreach ( $values as $k => $v )
|
||||
{
|
||||
if ( preg_match( '/^security_question_q_(\d+)$/', $k, $matches ) )
|
||||
{
|
||||
$answers[ $v ] = array(
|
||||
'answer_question_id' => $v,
|
||||
'answer_member_id' => $member->member_id,
|
||||
'answer_answer' => \IPS\Text\Encrypt::fromPlaintext( $values[ 'security_question_a_' . $matches[1] ] )->tag()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ( count( $answers ) )
|
||||
{
|
||||
\IPS\Db::i()->insert( 'core_security_answers', $answers );
|
||||
}
|
||||
|
||||
$member->members_bitoptions['has_security_answers'] = TRUE;
|
||||
}
|
||||
$member->save();
|
||||
}
|
||||
|
||||
/* Save custom field values */
|
||||
\IPS\Db::i()->replace( 'core_pfields_content', array_merge( array( 'member_id' => $member->member_id ), $profileFields ) );
|
||||
|
||||
/* Handle validation */
|
||||
$member->postRegistration();
|
||||
|
||||
/* Save and return */
|
||||
$member->save();
|
||||
return $member;
|
||||
}
|
||||
|
||||
@@ -370,6 +486,8 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function resend()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
$validating = \IPS\Db::i()->select( '*', 'core_validating', array( 'member_id=?', \IPS\Member::loggedIn()->member_id ) );
|
||||
|
||||
if ( !count( $validating ) )
|
||||
@@ -379,7 +497,14 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
|
||||
foreach( $validating as $reg )
|
||||
{
|
||||
\IPS\Email::buildFromTemplate( 'core', 'registration_validate', array( \IPS\Member::loggedIn(), $reg['vid'] ) )->send( \IPS\Member::loggedIn() );
|
||||
if ( $reg['email_sent'] and $reg['email_sent'] > ( time() - 900 ) )
|
||||
{
|
||||
\IPS\Output::i()->error( \IPS\Member::loggedIn()->language()->addToStack('validation_email_rate_limit', FALSE, array( 'sprintf' => array( \IPS\DateTime::ts( $reg['email_sent'] )->relative( \IPS\DateTime::RELATIVE_FORMAT_LOWER ) ) ) ), '1C223/4', 429, '', array( 'Retry-After' => \IPS\DateTime::ts( $reg['email_sent'] )->add( new \DateInterval( 'PT15M' ) )->format('r') ) );
|
||||
}
|
||||
|
||||
\IPS\Email::buildFromTemplate( 'core', $reg['email_chg'] ? 'email_change' : 'registration_validate', array( \IPS\Member::loggedIn(), $reg['vid'] ), \IPS\Email::TYPE_TRANSACTIONAL )->send( \IPS\Member::loggedIn() );
|
||||
|
||||
\IPS\Db::i()->update( 'core_validating', array( 'email_sent' => time() ), array( 'vid=?', $reg['vid'] ) );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=register&do=validating', 'front', 'register' ), 'reg_email_resent' );
|
||||
@@ -394,6 +519,7 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
if( \IPS\Request::i()->vid AND \IPS\Request::i()->mid )
|
||||
{
|
||||
/* Load record */
|
||||
try
|
||||
{
|
||||
$record = \IPS\Db::i()->select( '*', 'core_validating', array( 'vid=? AND member_id=? AND ( new_reg=? or email_chg=? )', \IPS\Request::i()->vid, \IPS\Request::i()->mid, 1, 1 ) )->first();
|
||||
@@ -403,18 +529,26 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->error( 'validate_no_record', '2S129/2', 404, '' );
|
||||
}
|
||||
|
||||
/* If we're using user validation, or this was anything other than a new registration (like an email change) we can go ahead and validate */
|
||||
if( \IPS\Settings::i()->reg_auth_type == 'user' or $record['email_chg'] )
|
||||
/* Validate */
|
||||
$member = \IPS\Member::load( \IPS\Request::i()->mid );
|
||||
if ( $record['new_reg'] )
|
||||
{
|
||||
\IPS\Member::load( \IPS\Request::i()->mid )->validate();
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( '' ), 'validate_confirmation' );
|
||||
$member->emailValidationConfirmed( $record );
|
||||
}
|
||||
/* Otherwise admin still needs to validate so we flag user validated */
|
||||
else
|
||||
{
|
||||
\IPS\Db::i()->update( 'core_validating', array( 'user_verified' => TRUE ), array( 'member_id=?', \IPS\Request::i()->mid ) );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( '' ), 'validate_email_confirmation' );
|
||||
$member->members_bitoptions['validating'] = FALSE;
|
||||
$member->save();
|
||||
|
||||
\IPS\Db::i()->delete( 'core_validating', array( 'member_id=?', $member->member_id ) );
|
||||
|
||||
/* Send a confirmation email */
|
||||
\IPS\Email::buildFromTemplate( 'core', 'email_address_changed', array( $member, $record['prev_email'] ), \IPS\Email::TYPE_TRANSACTIONAL )->send( $record['prev_email'], array(), array(), NULL, NULL, array( 'Reply-To' => \IPS\Settings::i()->email_in ) );
|
||||
}
|
||||
|
||||
/* Log in and Redirect */
|
||||
\IPS\Session::i()->setMember( $member );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( '' ), 'validate_email_confirmation' );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -425,8 +559,22 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function complete()
|
||||
{
|
||||
/* Check we are an incomplete member */
|
||||
if ( !\IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login', NULL, \IPS\Settings::i()->logins_over_https ) );
|
||||
}
|
||||
elseif ( \IPS\Member::loggedIn()->real_name and \IPS\Member::loggedIn()->email )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( '' ) );
|
||||
}
|
||||
|
||||
/* Build the form */
|
||||
$form = new \IPS\Helpers\Form( 'form', 'register_button' );
|
||||
if ( isset( \IPS\Request::i()->ref ) )
|
||||
{
|
||||
$form->hiddenValues['ref'] = \IPS\Request::i()->ref;
|
||||
}
|
||||
if( !\IPS\Member::loggedIn()->real_name OR \IPS\Member::loggedIn()->name === \IPS\Member::loggedIn()->language()->get('guest') )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'username', NULL, TRUE, array( 'accountUsername' => \IPS\Member::loggedIn() ) ) );
|
||||
@@ -463,30 +611,19 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->error( 'spam_denied_account', '2S272/1', 403, '' );
|
||||
}
|
||||
}
|
||||
|
||||
/* If email validation is enabled add a validating record */
|
||||
if( in_array( \IPS\Settings::i()->reg_auth_type, array( 'user', 'admin_user' ) ) )
|
||||
{
|
||||
$vid = md5( uniqid() );
|
||||
|
||||
\IPS\Db::i()->insert( 'core_validating', array(
|
||||
'vid' => $vid,
|
||||
'member_id' => \IPS\Member::loggedIn()->member_id,
|
||||
'entry_date' => time(),
|
||||
'new_reg' => 1,
|
||||
'email_chg' => 0,
|
||||
'user_verified' => FALSE,
|
||||
'ip_address' => \IPS\Request::i()->ipAddress()
|
||||
) );
|
||||
|
||||
\IPS\Member::loggedIn()->members_bitoptions['validating'] = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Save */
|
||||
\IPS\Member::loggedIn()->save();
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( '' ) );
|
||||
|
||||
/* Handle validation */
|
||||
\IPS\Member::loggedIn()->postRegistration( ( isset( $values['email_address'] ) ) ? FALSE : TRUE );
|
||||
|
||||
/* Set member as a full member in the session table */
|
||||
\IPS\Session::i()->setType( \IPS\Session\Front::LOGIN_TYPE_MEMBER );
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( \IPS\Login::getRegistrationDestination( \IPS\Member::loggedIn() ) );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('reg_complete_details');
|
||||
@@ -518,43 +655,55 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Build the form */
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->class = 'ipsForm_vertical';
|
||||
$form->add( new \IPS\Helpers\Form\Email( 'new_email', '', TRUE, array( 'accountEmail' => TRUE ) ) );
|
||||
$captcha = new \IPS\Helpers\Form\Captcha;
|
||||
if ( (string) $captcha !== '' )
|
||||
{
|
||||
$form->add( $captcha );
|
||||
}
|
||||
|
||||
/* Handle submissions */
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
/* Change the email */
|
||||
$oldEmail = \IPS\Member::loggedIn()->email;
|
||||
foreach ( \IPS\Login::handlers( TRUE ) as $handler )
|
||||
{
|
||||
try
|
||||
{
|
||||
$handler->changeEmail( \IPS\Member::loggedIn(), \IPS\Member::loggedIn()->email, $values['new_email'] );
|
||||
$handler->changeEmail( \IPS\Member::loggedIn(), $oldEmail, $values['new_email'] );
|
||||
}
|
||||
catch( \BadMethodCallException $e ) {}
|
||||
}
|
||||
|
||||
/* Delete any pending validation emails */
|
||||
if ( $pending['vid'] )
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_validating', array( 'member_id=? AND ( new_reg=1 or email_chg=1 )', \IPS\Member::loggedIn()->member_id ) );
|
||||
}
|
||||
|
||||
$vid = md5( uniqid() );
|
||||
|
||||
\IPS\Db::i()->insert( 'core_validating', array(
|
||||
'vid' => $vid,
|
||||
'member_id' => \IPS\Member::loggedIn()->member_id,
|
||||
'entry_date' => time(),
|
||||
'new_reg' => !$pending or $pending['new_reg'],
|
||||
'email_chg' => $pending and $pending['email_chg'],
|
||||
'user_verified' => ( \IPS\Settings::i()->reg_auth_type == 'admin' ) ?: FALSE,
|
||||
'ip_address' => \IPS\Request::i()->ipAddress()
|
||||
) );
|
||||
|
||||
\IPS\Member::loggedIn()->save();
|
||||
|
||||
\IPS\Email::buildFromTemplate( 'core', 'registration_validate', array( \IPS\Member::loggedIn(), $vid ) )->send( \IPS\Member::loggedIn() );
|
||||
|
||||
|
||||
/* If email validation is required, do that... */
|
||||
if ( in_array( \IPS\Settings::i()->reg_auth_type, array( 'user', 'admin_user' ) ) )
|
||||
{
|
||||
/* Delete any pending validation emails */
|
||||
if ( $pending['vid'] )
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_validating', array( 'member_id=? AND ( new_reg=1 or email_chg=1 )', \IPS\Member::loggedIn()->member_id ) );
|
||||
}
|
||||
|
||||
$vid = \IPS\Login::generateRandomString();
|
||||
|
||||
\IPS\Db::i()->insert( 'core_validating', array(
|
||||
'vid' => $vid,
|
||||
'member_id' => \IPS\Member::loggedIn()->member_id,
|
||||
'entry_date' => time(),
|
||||
'new_reg' => !$pending or $pending['new_reg'],
|
||||
'email_chg' => $pending and $pending['email_chg'],
|
||||
'user_verified' => ( \IPS\Settings::i()->reg_auth_type == 'admin' ) ?: FALSE,
|
||||
'ip_address' => \IPS\Request::i()->ipAddress(),
|
||||
'email_sent' => time(),
|
||||
) );
|
||||
|
||||
\IPS\Email::buildFromTemplate( 'core', $pending['email_chg'] ? 'email_change' : 'registration_validate', array( \IPS\Member::loggedIn(), $vid ), \IPS\Email::TYPE_TRANSACTIONAL )->send( \IPS\Member::loggedIn() );
|
||||
}
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( '' ) );
|
||||
}
|
||||
|
||||
@@ -575,8 +724,46 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C223/1', 403, '' );
|
||||
}
|
||||
|
||||
/* Delete Member */
|
||||
\IPS\Member::loggedIn()->delete();
|
||||
/* Make sure the user confirmed the deletion */
|
||||
\IPS\Request::i()->confirmedDelete( 'reg_cancel', 'reg_cancel_confirm', 'reg_cancel' );
|
||||
|
||||
/* Log the user out. Previously, we immediately deleted the account however this has been changed to let the cleanup task handle this instead. */
|
||||
\IPS\Request::i()->setCookie( 'member_id', NULL );
|
||||
\IPS\Request::i()->setCookie( 'pass_hash', NULL );
|
||||
\IPS\Request::i()->setCookie( 'anon_login', NULL );
|
||||
|
||||
foreach( \IPS\Request::i()->cookie as $name => $value )
|
||||
{
|
||||
if( mb_strpos( $name, "ipbforumpass_" ) !== FALSE )
|
||||
{
|
||||
\IPS\Request::i()->setCookie( $name, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset session global parameters */
|
||||
$_SESSION = array();
|
||||
|
||||
/* We have to explicitly reset the session cookie
|
||||
@link http://php.net/manual/en/function.session-destroy.php */
|
||||
$params = session_get_cookie_params();
|
||||
|
||||
setcookie( session_name(), '', time() - 42000, $params["path"], $params["domain"], $params["secure"], $params["httponly"] );
|
||||
|
||||
/* Then destroy the session itself */
|
||||
session_destroy();
|
||||
|
||||
/* Member sync callback */
|
||||
\IPS\Member::loggedIn()->memberSync( 'onLogout', array( \IPS\Http\Url::internal( '' ) ) );
|
||||
|
||||
/* Login handler callback */
|
||||
foreach ( \IPS\Login::handlers( TRUE ) as $k => $handler )
|
||||
{
|
||||
try
|
||||
{
|
||||
$handler->logoutAccount( \IPS\Member::loggedIn(), \IPS\Http\Url::internal( '' ) );
|
||||
}
|
||||
catch( \BadMethodCallException $e ) {}
|
||||
}
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( '' ), 'reg_canceled' );
|
||||
@@ -591,6 +778,10 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/* Generate form */
|
||||
$form = new \IPS\Helpers\Form;
|
||||
if ( isset( \IPS\Request::i()->ref ) )
|
||||
{
|
||||
$form->hiddenValues['ref'] = \IPS\Request::i()->ref;
|
||||
}
|
||||
$form->class = 'ipsForm_vertical';
|
||||
$form->add( new \IPS\Helpers\Form\Checkbox( 'reconfirm_checkbox', NULL, FALSE, array(), function( $val )
|
||||
{
|
||||
@@ -607,6 +798,19 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
\IPS\Member::loggedIn()->members_bitoptions['must_reaccept_terms'] = FALSE;
|
||||
\IPS\Member::loggedIn()->save();
|
||||
|
||||
if ( isset( \IPS\Request::i()->ref ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$ref = \IPS\Http\Url\Friendly::createFromString( base64_decode( \IPS\Request::i()->ref ) );
|
||||
if ( $ref instanceof \IPS\Http\Url\Internal )
|
||||
{
|
||||
\IPS\Output::i()->redirect( $ref );
|
||||
}
|
||||
}
|
||||
catch ( \Exception $e ) { }
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('') );
|
||||
}
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief User CP Controller
|
||||
* @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 10 Jun 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -54,11 +54,49 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$output = call_user_func( array( $this, "_{$area}" ) );
|
||||
}
|
||||
|
||||
|
||||
/* Display */
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('settings');
|
||||
\IPS\Output::i()->breadcrumb[] = array( NULL, \IPS\Member::loggedIn()->language()->addToStack('settings') );
|
||||
if ( !\IPS\Request::i()->isAjax() )
|
||||
{
|
||||
if ( \IPS\Request::i()->service )
|
||||
{
|
||||
$area = "{$area}_" . \IPS\Request::i()->service;
|
||||
}
|
||||
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/settings.css' ) );
|
||||
|
||||
if ( \IPS\Theme::i()->settings['responsive'] )
|
||||
{
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/settings_responsive.css' ) );
|
||||
}
|
||||
|
||||
if ( $output )
|
||||
{
|
||||
\IPS\Output::i()->output .= $this->_wrapOutputInTemplate( $area, $output );
|
||||
}
|
||||
}
|
||||
elseif ( $output )
|
||||
{
|
||||
\IPS\Output::i()->output .= $output;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap output in template
|
||||
*
|
||||
* @param string $area Active area
|
||||
* @param string $output Output
|
||||
* @return string
|
||||
*/
|
||||
protected function _wrapOutputInTemplate( $area, $output )
|
||||
{
|
||||
/* What can we do? */
|
||||
$canChangeEmail = FALSE;
|
||||
$canChangePassword = FALSE;
|
||||
$canChangeUsername = FALSE;
|
||||
$canConfigureMfa = FALSE;
|
||||
foreach ( \IPS\Login::handlers( TRUE ) as $k => $handler )
|
||||
{
|
||||
if ( \IPS\Member::loggedIn()->group['g_dname_changes'] and $handler->canChange( 'username', \IPS\Member::loggedIn() ) )
|
||||
@@ -74,6 +112,14 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
$canChangePassword = TRUE;
|
||||
}
|
||||
}
|
||||
foreach ( \IPS\MFA\MFAHandler::handlers() as $handler )
|
||||
{
|
||||
if ( $handler->isEnabled() and $handler->memberCanUseHandler( \IPS\Member::loggedIn() ) )
|
||||
{
|
||||
$canConfigureMfa = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$sigLimits = explode( ":", \IPS\Member::loggedIn()->group['g_signature_limits'] );
|
||||
$canChangeSignature = (bool) ( \IPS\Settings::i()->signatures_enabled && !$sigLimits[0] );
|
||||
@@ -81,21 +127,8 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
/* Add sync services */
|
||||
$services = \IPS\core\ProfileSync\ProfileSyncAbstract::services();
|
||||
|
||||
/* Display */
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('settings');
|
||||
\IPS\Output::i()->breadcrumb[] = array( NULL, \IPS\Member::loggedIn()->language()->addToStack('settings') );
|
||||
if ( !\IPS\Request::i()->isAjax() )
|
||||
{
|
||||
if ( \IPS\Request::i()->service )
|
||||
{
|
||||
$area = "{$area}_" . \IPS\Request::i()->service;
|
||||
}
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->settings( $area, $output, $canChangeEmail, $canChangePassword, $canChangeUsername, $canChangeSignature, $services );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->output = $output;
|
||||
}
|
||||
/* Return */
|
||||
return \IPS\Theme::i()->getTemplate( 'system' )->settings( $area, $output, $canChangeEmail, $canChangePassword, $canChangeUsername, $canChangeSignature, $services, $canConfigureMfa );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,6 +160,16 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
return \IPS\Theme::i()->getTemplate( 'system' )->settingsEmail();
|
||||
}
|
||||
|
||||
$mfaOutput = \IPS\MFA\MFAHandler::accessToArea( 'core', 'EmailChange', \IPS\Http\Url::internal( 'app=core&module=system&controller=settings&area=password', 'front', 'settings_password' ) );
|
||||
if ( $mfaOutput )
|
||||
{
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=settings&area=mfa', 'front', 'settings_mfa' ) );
|
||||
}
|
||||
\IPS\Output::i()->output = $mfaOutput;
|
||||
}
|
||||
|
||||
/* Do we have any pending validation emails? */
|
||||
try
|
||||
{
|
||||
@@ -139,20 +182,23 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Build the form */
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->addDummy( 'current_email', \IPS\Member::loggedIn()->email );
|
||||
$form->class = 'ipsForm_collapseTablet';
|
||||
$form->addDummy( 'current_email', htmlspecialchars( \IPS\Member::loggedIn()->email, \IPS\HTMLENTITIES, 'UTF-8', FALSE ) );
|
||||
$form->add( new \IPS\Helpers\Form\Email( 'new_email', '', TRUE, array( 'accountEmail' => TRUE ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'current_password', '', TRUE, array( 'validateFor' => \IPS\Member::loggedIn() ) ) );
|
||||
|
||||
/* Handle submissions */
|
||||
if ( $values = $form->values() )
|
||||
if ( !$mfaOutput and $values = $form->values() )
|
||||
{
|
||||
$oldEmail = \IPS\Member::loggedIn()->email;
|
||||
|
||||
/* Change the email */
|
||||
foreach ( \IPS\Login::handlers( TRUE ) as $handler )
|
||||
{
|
||||
/* We cannot update our email address in some login handlers, that's ok */
|
||||
try
|
||||
{
|
||||
$handler->changeEmail( \IPS\Member::loggedIn(), \IPS\Member::loggedIn()->email, $values['new_email'] );
|
||||
$handler->changeEmail( \IPS\Member::loggedIn(), $oldEmail, $values['new_email'] );
|
||||
}
|
||||
catch( \BadMethodCallException $e ){}
|
||||
}
|
||||
@@ -166,7 +212,7 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
/* Send a validation email if we need to */
|
||||
if ( \IPS\Settings::i()->reg_auth_type == 'user' or \IPS\Settings::i()->reg_auth_type == 'admin_user' )
|
||||
{
|
||||
$vid = md5( uniqid() );
|
||||
$vid = \IPS\Login::generateRandomString();
|
||||
|
||||
\IPS\Db::i()->insert( 'core_validating', array(
|
||||
'vid' => $vid,
|
||||
@@ -174,13 +220,14 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
'entry_date' => time(),
|
||||
'email_chg' => TRUE,
|
||||
'ip_address' => \IPS\Request::i()->ipAddress(),
|
||||
'prev_email' => \IPS\Member::loggedIn()->email
|
||||
'prev_email' => $oldEmail,
|
||||
'email_sent' => time(),
|
||||
) );
|
||||
|
||||
\IPS\Member::loggedIn()->members_bitoptions['validating'] = TRUE;
|
||||
\IPS\Member::loggedIn()->save();
|
||||
|
||||
\IPS\Email::buildFromTemplate( 'core', 'email_change', array( \IPS\Member::loggedIn(), $vid ) )->send( \IPS\Member::loggedIn() );
|
||||
\IPS\Email::buildFromTemplate( 'core', 'email_change', array( \IPS\Member::loggedIn(), $vid ), \IPS\Email::TYPE_TRANSACTIONAL )->send( \IPS\Member::loggedIn() );
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( '' ) );
|
||||
}
|
||||
@@ -188,6 +235,9 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
/* Or just redirect */
|
||||
else
|
||||
{
|
||||
/* Send a confirmation email */
|
||||
\IPS\Email::buildFromTemplate( 'core', 'email_address_changed', array( \IPS\Member::loggedIn(), $oldEmail ), \IPS\Email::TYPE_TRANSACTIONAL )->send( $oldEmail, array(), array(), NULL, NULL, array( 'Reply-To' => \IPS\Settings::i()->email_in ) );
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=settings&area=email', 'front', 'settings' ), 'email_changed' );
|
||||
}
|
||||
}
|
||||
@@ -207,12 +257,23 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
return \IPS\Theme::i()->getTemplate( 'system' )->settingsPassword();
|
||||
}
|
||||
|
||||
$mfaOutput = \IPS\MFA\MFAHandler::accessToArea( 'core', 'PasswordChange', \IPS\Http\Url::internal( 'app=core&module=system&controller=settings&area=password', 'front', 'settings_password' ) );
|
||||
if ( $mfaOutput )
|
||||
{
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=settings&area=mfa', 'front', 'settings_mfa' ) );
|
||||
}
|
||||
\IPS\Output::i()->output = $mfaOutput;
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->class = 'ipsForm_collapseTablet';
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'current_password', '', TRUE, array( 'validateFor' => \IPS\Member::loggedIn() ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'new_password', '', TRUE ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'new_password', '', TRUE, array( 'showMeter' => \IPS\Settings::i()->password_strength_meter ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'confirm_new_password', '', TRUE, array( 'confirm' => 'new_password' ) ) );
|
||||
|
||||
if ( $values = $form->values() )
|
||||
if ( !$mfaOutput and $values = $form->values() )
|
||||
{
|
||||
foreach ( \IPS\Login::handlers( TRUE ) as $handler )
|
||||
{
|
||||
@@ -223,17 +284,383 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
catch( \BadMethodCallException $e ){}
|
||||
}
|
||||
|
||||
\IPS\Member::loggedIn()->members_pass_salt = \IPS\Member::loggedIn()->generateSalt();
|
||||
\IPS\Member::loggedIn()->members_pass_hash = \IPS\Member::loggedIn()->encryptedPassword( $values['new_password'] );
|
||||
\IPS\Member::loggedIn()->save();
|
||||
|
||||
|
||||
/* If we have a pass_hash cookie, update it so we stay logged in on the next page load */
|
||||
if( isset( \IPS\Request::i()->cookie['pass_hash'] ) )
|
||||
{
|
||||
$expire = new \IPS\DateTime;
|
||||
$expire->add( new \DateInterval( 'P3M' ) );
|
||||
\IPS\Request::i()->setCookie( 'pass_hash', \IPS\Member::loggedIn()->member_login_key, $expire );
|
||||
}
|
||||
|
||||
/* Send a confirmation email */
|
||||
\IPS\Email::buildFromTemplate( 'core', 'password_changed', array(), \IPS\Email::TYPE_TRANSACTIONAL )->send( \IPS\Member::loggedIn(), array(), array(), NULL, NULL, array( 'Reply-To' => \IPS\Settings::i()->email_in ) );
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=settings&area=password', 'front', 'settings' ), 'password_changed' );
|
||||
}
|
||||
|
||||
return \IPS\Theme::i()->getTemplate( 'system' )->settingsPassword( $form );
|
||||
}
|
||||
|
||||
/**
|
||||
* MFA
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function _mfa()
|
||||
{
|
||||
/* Validate password */
|
||||
if ( !isset( $_SESSION['passwordValidatedForMfa'] ) )
|
||||
{
|
||||
$form = new \IPS\Helpers\Form( 'mfa_password', 'continue' );
|
||||
$form->class = 'ipsForm_collapseTablet';
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'password', '', TRUE, array( 'validateFor' => \IPS\Member::loggedIn() ) ) );
|
||||
if ( $form->values() )
|
||||
{
|
||||
$_SESSION['passwordValidatedForMfa'] = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate( 'system' )->settingsMfaPassword( $form );
|
||||
}
|
||||
}
|
||||
|
||||
/* Do MFA check */
|
||||
$mfaOutput = \IPS\MFA\MFAHandler::accessToArea( 'core', 'SecurityQuestions', \IPS\Http\Url::internal( 'app=core&module=system&controller=settings&area=mfa', 'front', 'settings_mfa' ) );
|
||||
if ( $mfaOutput )
|
||||
{
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=settings&area=mfa', 'front', 'settings_mfa' ) );
|
||||
}
|
||||
\IPS\Output::i()->output = $mfaOutput;
|
||||
}
|
||||
|
||||
/* Show it */
|
||||
$handlers = array();
|
||||
foreach ( \IPS\MFA\MFAHandler::handlers() as $key => $handler )
|
||||
{
|
||||
if ( $handler->isEnabled() and $handler->memberCanUseHandler( \IPS\Member::loggedIn() ) )
|
||||
{
|
||||
$handlers[ $key ] = $handler;
|
||||
}
|
||||
}
|
||||
return \IPS\Theme::i()->getTemplate( 'system' )->settingsMfa( $handlers );
|
||||
}
|
||||
|
||||
/**
|
||||
* Initial MFA Setup
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function initialMfa()
|
||||
{
|
||||
$ref = \IPS\Http\Url::internal('');
|
||||
if ( isset( \IPS\Request::i()->ref ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$ref = \IPS\Http\Url\Friendly::createFromString( base64_decode( \IPS\Request::i()->ref ) );
|
||||
}
|
||||
catch ( \Exception $e ) { }
|
||||
}
|
||||
|
||||
$handlers = array();
|
||||
foreach ( \IPS\MFA\MFAHandler::handlers() as $key => $handler )
|
||||
{
|
||||
if ( $handler->isEnabled() and $handler->memberCanUseHandler( \IPS\Member::loggedIn() ) )
|
||||
{
|
||||
$handlers[ $key ] = $handler;
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( \IPS\Request::i()->mfa_setup ) )
|
||||
{
|
||||
foreach ( $handlers as $key => $handler )
|
||||
{
|
||||
if ( ( count( $handlers ) == 1 ) or $key == \IPS\Request::i()->mfa_method )
|
||||
{
|
||||
if ( $handler->configurationScreenSubmit( \IPS\Member::loggedIn() ) )
|
||||
{
|
||||
$_SESSION['MFAAuthenticated'] = time();
|
||||
\IPS\Output::i()->redirect( $ref );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( $handlers as $key => $handler )
|
||||
{
|
||||
if ( $handler->memberHasConfiguredHandler( \IPS\Member::loggedIn() ) )
|
||||
{
|
||||
\IPS\Output::i()->redirect( $ref );
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( \IPS\Request::i()->_mfa ) and \IPS\Request::i()->_mfa == 'optout' )
|
||||
{
|
||||
\IPS\Member::loggedIn()->members_bitoptions['security_questions_opt_out'] = TRUE;
|
||||
\IPS\Member::loggedIn()->save();
|
||||
\IPS\Output::i()->redirect( $ref );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('reg_complete_details');
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( '2fa.css', 'core', 'global' ) );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'login', 'core', 'global' )->mfaSetup( $handlers, \IPS\Member::loggedIn(), \IPS\Http\Url::internal( 'app=core&module=system&controller=settings&do=initialMfa', 'front', 'settings' )->setQueryString( 'ref', base64_encode( $ref ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable MFA
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function enableMfa()
|
||||
{
|
||||
/* Get the handler */
|
||||
$handlers = \IPS\MFA\MFAHandler::handlers();
|
||||
$key = \IPS\Request::i()->type;
|
||||
if ( !isset( $handlers[ $key ] ) or !$handlers[ $key ]->isEnabled() or !$handlers[ $key ]->memberCanUseHandler( \IPS\Member::loggedIn() ) or \IPS\MFA\MFAHandler::accessToArea( 'core', 'SecurityQuestions', \IPS\Http\Url::internal( 'app=core&module=system&controller=settings&area=mfa', 'front', 'settings_mfa' ) ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C122/M', 404, '' );
|
||||
}
|
||||
|
||||
/* Include the CSS we'll need */
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( '2fa.css', 'core', 'global' ) );
|
||||
|
||||
/* Show the list again as the backdrop */
|
||||
\IPS\Output::i()->output = $this->_wrapOutputInTemplate( 'mfa', $this->_mfa() );
|
||||
|
||||
/* Did we just submit it? */
|
||||
if ( isset( \IPS\Request::i()->mfa_setup ) and $handlers[ $key ]->configurationScreenSubmit( \IPS\Member::loggedIn() ) )
|
||||
{
|
||||
\IPS\Member::loggedIn()->members_bitoptions['security_questions_opt_out'] = FALSE;
|
||||
\IPS\Member::loggedIn()->save();
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=settings&area=mfa', 'front', 'settings_mfa' ) );
|
||||
}
|
||||
|
||||
/* And put the configruation modal over the top */
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('settings');
|
||||
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'system' )->settingsMfaSetup( $handlers[ $key ]->configurationScreen( \IPS\Member::loggedIn() ), \IPS\Http\Url::internal( 'app=core&module=system&controller=settings&area=mfa&do=enableMfa&type=' . $key, 'front', 'settings_mfa' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable MFA
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function disableMfa()
|
||||
{
|
||||
/* Get the handler */
|
||||
$handlers = \IPS\MFA\MFAHandler::handlers();
|
||||
$key = \IPS\Request::i()->type;
|
||||
if ( !isset( $handlers[ $key ] ) or !$handlers[ $key ]->isEnabled() or !$handlers[ $key ]->memberCanUseHandler( \IPS\Member::loggedIn() ) or \IPS\MFA\MFAHandler::accessToArea( 'core', 'SecurityQuestions', \IPS\Http\Url::internal( 'app=core&module=system&controller=settings&area=mfa', 'front', 'settings_mfa' ) ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C122/N', 404, '' );
|
||||
}
|
||||
|
||||
/* Disable it */
|
||||
$handlers[ $key ]->disableHandlerForMember( \IPS\Member::loggedIn() );
|
||||
\IPS\Member::loggedIn()->save();
|
||||
|
||||
/* If we have now disabled everything, save that we have opted out */
|
||||
if ( \IPS\Settings::i()->mfa_required_groups != '*' and !\IPS\Member::loggedIn()->inGroup( explode( ',', \IPS\Settings::i()->mfa_required_groups ) ) )
|
||||
{
|
||||
$enabledHandlers = FALSE;
|
||||
foreach ( $handlers as $handler )
|
||||
{
|
||||
if ( $handler->memberHasConfiguredHandler( \IPS\Member::loggedIn() ) )
|
||||
{
|
||||
$enabledHandlers = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !$enabledHandlers )
|
||||
{
|
||||
\IPS\Member::loggedIn()->members_bitoptions['security_questions_opt_out'] = TRUE;
|
||||
\IPS\Member::loggedIn()->save();
|
||||
}
|
||||
}
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=settings&area=mfa', 'front', 'settings_mfa' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Security Questions
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function _securityquestions()
|
||||
{
|
||||
$handler = new \IPS\MFA\SecurityQuestions\Handler();
|
||||
|
||||
if ( !$handler->isEnabled() )
|
||||
{
|
||||
\IPS\Output::i()->error( 'requested_route_404', '2C122/J', 404, '' );
|
||||
}
|
||||
|
||||
$url = \IPS\Http\Url::internal( 'app=core&module=system&controller=settings&area=securityquestions', 'front', 'settings_securityquestions' );
|
||||
if ( isset( \IPS\Request::i()->initial ) )
|
||||
{
|
||||
if ( isset( \IPS\Request::i()->ref ) )
|
||||
{
|
||||
$url = $url->setQueryString( 'ref', \IPS\Request::i()->ref );
|
||||
}
|
||||
|
||||
if ( !$handler->memberCanUseHandler( \IPS\Member::loggedIn() ) or $handler->memberHasConfiguredHandler( \IPS\Member::loggedIn() ) )
|
||||
{
|
||||
$ref = NULL;
|
||||
if ( isset( \IPS\Request::i()->ref ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$ref = \IPS\Http\Url::createFromString( base64_decode( \IPS\Request::i()->ref ) );
|
||||
if ( !( $ref instanceof \IPS\Http\Url\Internal ) )
|
||||
{
|
||||
$ref = NULL;
|
||||
}
|
||||
}
|
||||
catch ( \Exception $e ) { }
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( $ref ?: \IPS\Http\Url::internal( '' ) );
|
||||
}
|
||||
|
||||
$url = $url->setQueryString( 'initial', 1 );
|
||||
}
|
||||
elseif ( $handler->memberHasConfiguredHandler( \IPS\Member::loggedIn() ) )
|
||||
{
|
||||
if ( isset( \IPS\Request::i()->_securityQuestionSetup ) )
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate( 'system', 'core' )->securityQuestionsFinished();
|
||||
}
|
||||
elseif ( $output = \IPS\MFA\MFAHandler::accessToArea( 'core', 'SecurityQuestions', $url ) )
|
||||
{
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
|
||||
$output = $handler->configurationForm( \IPS\Member::loggedIn(), $url, !isset( \IPS\Request::i()->initial ) );
|
||||
|
||||
if ( isset( \IPS\Request::i()->initial ) )
|
||||
{
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
\IPS\Output::i()->output = $output;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* MFA Email Recovery
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function mfarecovery()
|
||||
{
|
||||
/* Who are we */
|
||||
if ( isset( $_SESSION['processing2FA'] ) )
|
||||
{
|
||||
$member = \IPS\Member::load( $_SESSION['processing2FA']['memberId'] );
|
||||
}
|
||||
else
|
||||
{
|
||||
$member = \IPS\Member::loggedIn();
|
||||
}
|
||||
|
||||
/* Can we use this? */
|
||||
if ( !$member->member_id or !( ( $member->failed_mfa_attempts >= \IPS\Settings::i()->security_questions_tries and \IPS\Settings::i()->mfa_lockout_behaviour == 'email' ) or in_array( 'email', explode( ',', \IPS\Settings::i()->mfa_forgot_behaviour ) ) ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C122/L', 403, '' );
|
||||
}
|
||||
|
||||
/* If we have an existing validation record, we can just reuse it */
|
||||
$sendEmail = TRUE;
|
||||
try
|
||||
{
|
||||
$existing = \IPS\Db::i()->select( array( 'vid', 'email_sent' ), 'core_validating', array( 'member_id=? AND forgot_security=1', $member->member_id ) )->first();
|
||||
$vid = $existing['vid'];
|
||||
|
||||
/* If we sent an email within the last 15 minutes, don't send another one otherwise someone could be a nuisence */
|
||||
if ( $existing['email_sent'] and $existing['email_sent'] > ( time() - 900 ) )
|
||||
{
|
||||
$sendEmail = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Db::i()->update( 'core_validating', array( 'email_sent' => time() ), array( 'vid=?', $vid ) );
|
||||
}
|
||||
}
|
||||
catch ( \UnderflowException $e )
|
||||
{
|
||||
$vid = md5( $member->members_pass_hash . \IPS\Login::generateRandomString() );
|
||||
|
||||
\IPS\Db::i()->insert( 'core_validating', array(
|
||||
'vid' => $vid,
|
||||
'member_id' => $member->member_id,
|
||||
'entry_date' => time(),
|
||||
'forgot_security' => 1,
|
||||
'ip_address' => \IPS\Request::i()->ipAddress(),
|
||||
'email_sent' => time(),
|
||||
) );
|
||||
}
|
||||
|
||||
/* Send email */
|
||||
if ( $sendEmail )
|
||||
{
|
||||
\IPS\Email::buildFromTemplate( 'core', 'mfaRecovery', array( $member, $vid ), \IPS\Email::TYPE_TRANSACTIONAL )->send( $member );
|
||||
$message = "mfa_recovery_email_sent";
|
||||
}
|
||||
else
|
||||
{
|
||||
$message = "mfa_recovery_email_already_sent";
|
||||
}
|
||||
|
||||
/* Show confirmation page with further instructions */
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('mfa_account_recovery');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->mfaAccountRecovery( $message );
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate MFA Email Recovery
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function mfarecoveryvalidate()
|
||||
{
|
||||
/* Validate */
|
||||
try
|
||||
{
|
||||
$record = \IPS\Db::i()->select( '*', 'core_validating', array( 'vid=? AND member_id=? AND forgot_security=1', \IPS\Request::i()->vid, \IPS\Request::i()->mid ) )->first();
|
||||
}
|
||||
catch ( \UnderflowException $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'mfa_recovery_no_validation_key', '2C122/K', 410, '' );
|
||||
}
|
||||
|
||||
/* Remove all MFA */
|
||||
$member = \IPS\Member::load( $record['member_id'] );
|
||||
foreach ( \IPS\MFA\MFAHandler::handlers() as $key => $handler )
|
||||
{
|
||||
$handler->disableHandlerForMember( $member );
|
||||
}
|
||||
$member->failed_mfa_attempts = 0;
|
||||
$member->save();
|
||||
|
||||
/* Delete validating record */
|
||||
\IPS\Db::i()->delete( 'core_validating', array( 'member_id=? AND forgot_security=1', $member->member_id ) );
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( '' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Username
|
||||
*
|
||||
@@ -290,7 +717,8 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/* Build form */
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'new_username', '', TRUE, array( 'accountUsername' => TRUE ) ) );
|
||||
$form->class = 'ipsForm_collapseTablet';
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'new_username', '', TRUE, array( 'accountUsername' => \IPS\Member::loggedIn() ) ) );
|
||||
|
||||
/* Handle submissions */
|
||||
if ( $values = $form->values() )
|
||||
@@ -364,6 +792,7 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Build form */
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->class = 'ipsForm_collapseTablet';
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'view_sigs', \IPS\Member::loggedIn()->members_bitoptions['view_sigs'], FALSE ) );
|
||||
$form->add( new \IPS\Helpers\Form\Editor( 'signature', \IPS\Member::loggedIn()->signature, FALSE, array( 'app' => 'core', 'key' => 'Signatures', 'autoSaveKey' => "frontsig-" .\IPS\Member::loggedIn()->member_id, 'attachIds' => array( \IPS\Member::loggedIn()->member_id ) ) ) );
|
||||
|
||||
@@ -373,8 +802,8 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
if( $values['signature'] )
|
||||
{
|
||||
/* Check Limits */
|
||||
$signature = new \DOMDocument;
|
||||
$signature->loadHTML( $values['signature'] );
|
||||
$signature = new \IPS\Xml\DOMDocument( '1.0', 'UTF-8' );
|
||||
$signature->loadHTML( \IPS\Xml\DOMDocument::wrapHtml( $values['signature'] ) );
|
||||
|
||||
$errors = array();
|
||||
|
||||
@@ -383,11 +812,22 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$errors[] = \IPS\Member::loggedIn()->language()->addToStack('sig_num_links_exceeded');
|
||||
}
|
||||
|
||||
|
||||
/* Number of Images */
|
||||
if ( is_numeric( $sigLimits[1] ) and $signature->getElementsByTagName('img')->length > $sigLimits[1] )
|
||||
if ( is_numeric( $sigLimits[1] ) and $signature->getElementsByTagName('img')->length > 0 )
|
||||
{
|
||||
$errors[] = \IPS\Member::loggedIn()->language()->addToStack('sig_num_images_exceeded');
|
||||
$imageCount = 0;
|
||||
foreach ( $signature->getElementsByTagName('img') as $img )
|
||||
{
|
||||
if( !$img->hasAttribute("data-emoticon") )
|
||||
{
|
||||
$imageCount++;
|
||||
}
|
||||
}
|
||||
if( $imageCount > $sigLimits[1] )
|
||||
{
|
||||
$errors[] = \IPS\Member::loggedIn()->language()->addToStack('sig_num_images_exceeded');
|
||||
}
|
||||
}
|
||||
|
||||
/* Size of images */
|
||||
@@ -395,10 +835,29 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
foreach ( $signature->getElementsByTagName('img') as $image )
|
||||
{
|
||||
$src = $image->getAttribute('src');
|
||||
\IPS\Output::i()->parseFileObjectUrls( $src );
|
||||
$attachId = $image->getAttribute('data-fileid');
|
||||
$checkSrc = TRUE;
|
||||
|
||||
if( $attachId )
|
||||
{
|
||||
try
|
||||
{
|
||||
$attachment = \IPS\Db::i()->select( 'attach_location, attach_thumb_location', 'core_attachments', array( 'attach_id=?', $attachId ) )->first();
|
||||
$imageProperties = \IPS\File::get( 'core_Attachment', $attachment['attach_thumb_location'] ?: $attachment['attach_location'] )->getImageDimensions();
|
||||
|
||||
$checkSrc = FALSE;
|
||||
}
|
||||
catch( \UnderflowException $e ){}
|
||||
}
|
||||
|
||||
if( $checkSrc )
|
||||
{
|
||||
$src = $image->getAttribute('src');
|
||||
\IPS\Output::i()->parseFileObjectUrls( $src );
|
||||
|
||||
$imageProperties = @getimagesize( $src );
|
||||
}
|
||||
|
||||
$imageProperties = @getimagesize( $src );
|
||||
if( is_array( $imageProperties ) AND count( $imageProperties ) )
|
||||
{
|
||||
if( $imageProperties[0] > $sigLimits[2] OR $imageProperties[1] > $sigLimits[3] )
|
||||
@@ -408,13 +867,22 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
else
|
||||
{
|
||||
$errors[] = \IPS\Member::loggedIn()->language()->addToStack( 'sig_imagenotretrievable' );
|
||||
$errors[] = \IPS\Member::loggedIn()->language()->addToStack( 'sig_imagenotretrievable', FALSE, array( 'sprintf' => array( $src ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Lines */
|
||||
if ( is_numeric( $sigLimits[5] ) and ( $signature->getElementsByTagName('p')->length + $signature->getElementsByTagName('br')->length ) > $sigLimits[5] )
|
||||
$preBreaks = 0;
|
||||
|
||||
/* Make sure we are not trying to bypass the limit by using <pre> tags, which will not have <p> or <br> tags in its content */
|
||||
foreach( $signature->getElementsByTagName('pre') AS $pre )
|
||||
{
|
||||
$content = nl2br( trim( $pre->nodeValue ) );
|
||||
$preBreaks += count( explode( "<br />", $content ) );
|
||||
}
|
||||
|
||||
if ( is_numeric( $sigLimits[5] ) and ( $signature->getElementsByTagName('p')->length + $signature->getElementsByTagName('br')->length + $preBreaks ) > $sigLimits[5] )
|
||||
{
|
||||
$errors[] = \IPS\Member::loggedIn()->language()->addToStack('sig_num_lines_exceeded');
|
||||
}
|
||||
@@ -463,6 +931,9 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
elseif ( isset( \IPS\Request::i()->disassociate ) )
|
||||
{
|
||||
/* CSRF check */
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
/* Check they have another way of signing in */
|
||||
$isOkay = FALSE;
|
||||
foreach ( \IPS\Login::handlers() as $handler )
|
||||
@@ -490,30 +961,19 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->class = 'ipsForm_vertical';
|
||||
$form->add( new \IPS\Helpers\Form\Checkbox( 'profilesync_photo', $settings['photo'], FALSE, array( 'labelSprintf' => array( \IPS\Member::loggedIn()->language()->addToStack( $serviceName ) ) ) ) );
|
||||
if ( method_exists( $obj, 'photo' ) )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Checkbox( 'profilesync_photo', $settings['photo'], FALSE, array( 'labelSprintf' => array( \IPS\Member::loggedIn()->language()->addToStack( $serviceName ) ) ) ) );
|
||||
}
|
||||
|
||||
if ( method_exists( $obj, 'cover' ) )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Checkbox( 'profilesync_cover', $settings['cover'], FALSE, array( 'labelSprintf' => array( \IPS\Member::loggedIn()->language()->addToStack( $serviceName ) ) ) ) );
|
||||
}
|
||||
|
||||
if ( method_exists( $obj, 'status' ) and \IPS\Member::loggedIn()->canAccessModule( \IPS\Application\Module::get( 'core', 'members' ) ) and !\IPS\Member::loggedIn()->members_bitoptions['bw_no_status_update'] )
|
||||
if ( $obj->canImportStatus( \IPS\Member::loggedIn() ) )
|
||||
{
|
||||
$options = array();
|
||||
if ( !\IPS\Member::loggedIn()->group['gbw_no_status_import'] )
|
||||
{
|
||||
$options['import'] = \IPS\Member::loggedIn()->language()->addToStack('profilesync_import_status', FALSE, array( 'sprintf' => array( \IPS\Member::loggedIn()->language()->addToStack( $serviceName ) ) ) );
|
||||
}
|
||||
if ( method_exists( $obj, 'exportStatus' ) )
|
||||
{
|
||||
$options['export'] = \IPS\Member::loggedIn()->language()->addToStack('profilesync_export_status', FALSE, array( 'sprintf' => array( \IPS\Member::loggedIn()->language()->addToStack( $serviceName ) ) ) );
|
||||
}
|
||||
$options['none'] = \IPS\Member::loggedIn()->language()->addToStack('profilesync_status_none');
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'profilesync_status', $settings['status'], FALSE, array(
|
||||
'labelSprintf' => array( \IPS\Member::loggedIn()->language()->addToStack( $serviceName ) ),
|
||||
'options' => $options,
|
||||
'parse' => FALSE
|
||||
) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Checkbox( 'profilesync_status', $settings['status'] == 'import', FALSE, array( 'labelSprintf' => array( \IPS\Member::loggedIn()->language()->addToStack( $serviceName ) ) ) ) );
|
||||
}
|
||||
|
||||
if ( $values = $form->values() )
|
||||
@@ -521,7 +981,7 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
$obj->save( $values );
|
||||
}
|
||||
|
||||
$photo = $obj->photo();
|
||||
$photo = ( method_exists( $obj, 'photo' ) ) ? $obj->photo() : NULL;
|
||||
return \IPS\Theme::i()->getTemplate( 'system' )->settingsProfileSync( $photo instanceof \IPS\File ? $photo->url : $photo, $headline, method_exists( $obj, 'status' ) ? $obj->status() : NULL, $form, $service, "profilesync__{$service}", ( $settings['photo'] or $settings['cover'] or $settings['status'] ) );
|
||||
}
|
||||
else
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Splash Controller
|
||||
* @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 21 Jun 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Terms of Use
|
||||
* @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 25 Sept 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -37,4 +37,41 @@ class _terms extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->terms();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dismiss Terms
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function dismiss()
|
||||
{
|
||||
\IPS\Request::i()->setCookie( 'guestTermsDismissed', 1, NULL, FALSE );
|
||||
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->json( array( 'message' => \IPS\Member::loggedIn()->language()->addToStack( 'terms_dismissed' ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( isset( \IPS\Request::i()->ref ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$url = \IPS\Http\Url::createFromString( base64_decode( \IPS\Request::i()->ref ) );
|
||||
}
|
||||
catch( \IPS\Http\Url\Exception $e )
|
||||
{
|
||||
$url = NULL;
|
||||
}
|
||||
|
||||
if ( $url instanceof \IPS\Http\Url\Internal )
|
||||
{
|
||||
\IPS\Output::i()->redirect( $url, 'terms_dismissed' );
|
||||
}
|
||||
}
|
||||
|
||||
/* Still here? Just redirect to the index */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( '' ), 'terms_dismissed' );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Theme Changer
|
||||
* @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 17 Dec 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -58,6 +58,12 @@ class _theme extends \IPS\Dispatcher\Controller
|
||||
\IPS\Request::i()->setCookie( 'vseThemeId', 0 );
|
||||
}
|
||||
|
||||
if ( \IPS\Member::loggedIn()->members_bitoptions['bw_using_skin_gen'] )
|
||||
{
|
||||
\IPS\Member::loggedIn()->members_bitoptions['bw_using_skin_gen'] = 0;
|
||||
\IPS\Member::loggedIn()->save();
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( ( !empty( $_SERVER['HTTP_REFERER'] ) ) ? \IPS\Http\Url::external( $_SERVER['HTTP_REFERER'] ) : \IPS\Http\Url::internal( '' ) );
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Allow users to unsubscribe from site updates
|
||||
* @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 12 Jun 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -44,7 +44,7 @@ class _unsubscribe extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/* Verify the key is correct */
|
||||
if ( \IPS\Request::i()->key == md5( $member->email . ':' . $member->members_pass_hash ) )
|
||||
if ( \IPS\Login::compareHashes( md5( $member->email . ':' . $member->members_pass_hash ), (string) \IPS\Request::i()->key ) )
|
||||
{
|
||||
/* Set the member not to receive future emails */
|
||||
$member->allow_admin_mails = 0;
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Visual Language Editor
|
||||
* @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 27 Jun 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -63,6 +63,8 @@ class _vle extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
public function set()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
try
|
||||
{
|
||||
$word = \IPS\Db::i()->select( '*', 'core_sys_lang_words', array( 'lang_id=? AND word_key=?', \IPS\Member::loggedIn()->language()->id, \IPS\Request::i()->key ) )->first();
|
||||
@@ -72,11 +74,20 @@ class _vle extends \IPS\Dispatcher\Controller
|
||||
$word = NULL;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$application = \IPS\Application::load( $word['word_app'] );
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( $word !== NULL )
|
||||
{
|
||||
if ( $word['word_export'] )
|
||||
{
|
||||
\IPS\Db::i()->update( 'core_sys_lang_words', array( 'word_custom' => \IPS\Request::i()->value, 'word_custom_version' => \IPS\Application::load( $word['word_app'] )->long_version ), array( 'word_id=?', $word['word_id'] ) );
|
||||
\IPS\Db::i()->update( 'core_sys_lang_words', array( 'word_custom' => \IPS\Request::i()->value, 'word_custom_version' => $application->long_version ), array( 'word_id=?', $word['word_id'] ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -94,6 +105,7 @@ class _vle extends \IPS\Dispatcher\Controller
|
||||
|
||||
\IPS\Db::i()->insert( 'core_admin_logs', array(
|
||||
'member_id' => \IPS\Member::loggedIn()->member_id,
|
||||
'member_name' => \IPS\Member::loggedIn()->name,
|
||||
'ctime' => time(),
|
||||
'note' => json_encode( array( $word['word_key'] => FALSE, \IPS\Member::loggedIn()->language()->title => FALSE ) ),
|
||||
'ip_address' => \IPS\Request::i()->ipAddress(),
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Visual Theme Editor
|
||||
* @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 7 Nov 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -144,6 +144,8 @@ class _vse extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
/* Update the current member */
|
||||
\IPS\Member::loggedIn()->members_bitoptions['bw_using_skin_gen'] = 0;
|
||||
\IPS\Member::loggedIn()->save();
|
||||
@@ -179,6 +181,8 @@ class _vse extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
\IPS\Output::i()->json( 'NO_PERMISSION', 403 );
|
||||
}
|
||||
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
$theme = null;
|
||||
|
||||
@@ -199,7 +203,7 @@ class _vse extends \IPS\Dispatcher\Controller
|
||||
|
||||
$theme->vseSave( \IPS\Request::i()->css, \IPS\Request::i()->customcss, \IPS\Request::i()->settings, \IPS\Request::i()->values );
|
||||
|
||||
\IPS\File::getClass('core_Theme')->deleteContainer( 'css_built_' . $this->id );
|
||||
\IPS\File::getClass('core_Theme')->deleteContainer( 'css_built_' . $theme->id );
|
||||
$theme->css_map = array();
|
||||
$theme->save();
|
||||
foreach( $theme->children() as $child )
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Member Warnings
|
||||
* @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 18 Jul 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -172,6 +172,8 @@ class _warnings extends \IPS\Content\Controller
|
||||
*/
|
||||
protected function acknowledge()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
/* Load the member */
|
||||
$member = \IPS\Member::load( \IPS\Request::i()->id );
|
||||
if ( !$member->member_id )
|
||||
@@ -197,21 +199,21 @@ class _warnings extends \IPS\Content\Controller
|
||||
/* Acknowledge it */
|
||||
$warning->acknowledged = TRUE;
|
||||
$warning->save();
|
||||
$member->members_bitoptions['unacknowledged_warnings'] = (bool) \IPS\Db::i()->select( 'COUNT(*)', 'core_members_warn_logs', array( "wl_member=? AND wl_acknowledged=0", $member->member_id ) )->first();
|
||||
$member->members_bitoptions['unacknowledged_warnings'] = (bool) \IPS\Db::i()->select( 'COUNT(*)', 'core_members_warn_logs', array( "wl_member=? AND wl_acknowledged=0", $member->member_id ), NULL, NULL, NULL, NULL, \IPS\Db::SELECT_FROM_WRITE_SERVER )->first();
|
||||
$member->save();
|
||||
|
||||
/* Redirect */
|
||||
if ( isset( $_SERVER['HTTP_REFERER'] ) )
|
||||
{
|
||||
$url = new \IPS\Http\Url( $_SERVER['HTTP_REFERER'] );
|
||||
if ( $url->isInternal )
|
||||
$url = \IPS\Http\Url\Friendly::createFromString( $_SERVER['HTTP_REFERER'] );
|
||||
if ( $url instanceof \IPS\Http\Url\Internal )
|
||||
{
|
||||
\IPS\Output::i()->redirect( $url );
|
||||
return;
|
||||
}
|
||||
}
|
||||
\IPS\Output::i()->redirect( $warning->url() );
|
||||
|
||||
|
||||
\IPS\Output::i()->redirect( $warning->url() );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -275,6 +277,7 @@ class _warnings extends \IPS\Content\Controller
|
||||
'points_override' => TRUE,
|
||||
'remove' => $remove,
|
||||
'remove_override' => TRUE,
|
||||
'notes' => NULL,
|
||||
) );
|
||||
}
|
||||
|
||||
@@ -307,6 +310,7 @@ class _warnings extends \IPS\Content\Controller
|
||||
'points_override' => $reason->points_override,
|
||||
'remove' => $remove,
|
||||
'remove_override' => $reason->remove_override,
|
||||
'notes' => $reason->notes,
|
||||
) );
|
||||
}
|
||||
|
||||
@@ -317,6 +321,7 @@ class _warnings extends \IPS\Content\Controller
|
||||
'points_override' => FALSE,
|
||||
'remove' => $remove,
|
||||
'remove_override' => FALSE,
|
||||
'notes' => NULL,
|
||||
) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Sidebar Widgets
|
||||
* @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 19 Nov 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -237,6 +237,8 @@ class _widgets extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
\IPS\Output::i()->error( 'invalid_widget_area', '3S172/2', 403, '' );
|
||||
}
|
||||
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
$newOrder = array();
|
||||
$seen = array();
|
||||
|
||||
Reference in new issue
Block a user