Version 4.3.0
This commit is contained in:
1 parent
96997ddd8e
commit
fe1acf984a
1349 files changed
+116159
-67711
No files matched your search
+30
-9
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief memberactivity
|
||||
* @brief Community Activity
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
@@ -18,9 +18,9 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
}
|
||||
|
||||
/**
|
||||
* memberactivity
|
||||
* Community Activity
|
||||
*/
|
||||
class _memberactivity extends \IPS\Dispatcher\Controller
|
||||
class _communityactivity extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
@@ -29,7 +29,7 @@ class _memberactivity extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'memberactivity_manage' );
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'communityactivity_manage' );
|
||||
parent::execute();
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ class _memberactivity extends \IPS\Dispatcher\Controller
|
||||
protected function manage()
|
||||
{
|
||||
$chart = new \IPS\Helpers\Chart\Callback(
|
||||
\IPS\Http\Url::internal( 'app=core&module=activitystats&controller=memberactivity' ),
|
||||
\IPS\Http\Url::internal( 'app=core&module=activitystats&controller=communityactivity' ),
|
||||
array( $this, 'getResults' ),
|
||||
'',
|
||||
array(
|
||||
@@ -67,7 +67,7 @@ class _memberactivity extends \IPS\Dispatcher\Controller
|
||||
return;
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__core_activitystats_memberactivity');
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__core_activitystats_communityactivity');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'stats' )->activitymessage();
|
||||
\IPS\Output::i()->output .= (string) $chart;
|
||||
}
|
||||
@@ -82,8 +82,29 @@ class _memberactivity extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/* Get results */
|
||||
$results = array();
|
||||
|
||||
$results = array_replace_recursive( $results, $this->getSqlResults( 'core_search_index', 'index_date_updated', 'index_author', $chart ) );
|
||||
|
||||
if ( \IPS\Settings::i()->search_method == 'mysql' )
|
||||
{
|
||||
$results = array_replace_recursive( $results, $this->getSqlResults( 'core_search_index', 'index_date_updated', 'index_author', $chart ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach ( \IPS\Application::allExtensions( 'core', 'ContentRouter' ) as $contentRouter )
|
||||
{
|
||||
foreach ( $contentRouter->classes as $class )
|
||||
{
|
||||
if ( isset( $class::$databaseColumnMap['author'] ) )
|
||||
{
|
||||
$results = array_replace_recursive( $results, $this->getSqlResults(
|
||||
$class::$databaseTable,
|
||||
$class::$databasePrefix . ( isset( $class::$databaseColumnMap['updated'] ) ? $class::$databaseColumnMap['updated'] : $class::$databaseColumnMap['date'] ),
|
||||
$class::$databasePrefix . $class::$databaseColumnMap['author'],
|
||||
$chart
|
||||
) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$results = array_replace_recursive( $results, $this->getSqlResults( 'core_reputation_index', 'rep_date', 'member_id', $chart ) );
|
||||
$results = array_replace_recursive( $results, $this->getSqlResults( 'core_follow', 'follow_added', 'follow_member_id', $chart ) );
|
||||
|
||||
@@ -140,7 +161,7 @@ class _memberactivity extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* First we need to get search index activity */
|
||||
$fromUnixTime = "FROM_UNIXTIME( IFNULL( {$date}, 0 ) )";
|
||||
if ( !$chart->timezoneError and \IPS\Member::loggedIn()->timezone and in_array( \IPS\Member::loggedIn()->timezone, \DateTimeZone::listIdentifiers() ) )
|
||||
if ( !$chart->timezoneError and \IPS\Member::loggedIn()->timezone and in_array( \IPS\Member::loggedIn()->timezone, \IPS\DateTime::getTimezoneIdentifiers() ) )
|
||||
{
|
||||
$fromUnixTime = "CONVERT_TZ( {$fromUnixTime}, @@session.time_zone, '" . \IPS\Db::i()->escape_string( \IPS\Member::loggedIn()->timezone ) . "' )";
|
||||
}
|
||||
@@ -133,6 +133,13 @@ class _keywords extends \IPS\Dispatcher\Controller
|
||||
try
|
||||
{
|
||||
$class = $data['class'];
|
||||
|
||||
/* Check that the class exists */
|
||||
if( !class_exists( $class ) )
|
||||
{
|
||||
throw new \InvalidArgumentException;
|
||||
}
|
||||
|
||||
$item = $class::load( $data['id'] );
|
||||
|
||||
return $item->author()->link();
|
||||
@@ -149,6 +156,13 @@ class _keywords extends \IPS\Dispatcher\Controller
|
||||
try
|
||||
{
|
||||
$class = $data['class'];
|
||||
|
||||
/* Check that the class exists */
|
||||
if( !class_exists( $class ) )
|
||||
{
|
||||
throw new \InvalidArgumentException;
|
||||
}
|
||||
|
||||
$item = $class::load( $data['id'] );
|
||||
|
||||
return \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->basicUrl( $item->url(), TRUE, ( $item instanceof \IPS\Content\Comment ) ? $item->item()->mapped('title') : $item->mapped('title'), TRUE );
|
||||
@@ -162,7 +176,7 @@ class _keywords extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Display */
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__core_activitystats_keywords');
|
||||
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'global', 'core' )->block( 'title', (string) $table );
|
||||
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'global', 'core' )->block( 'title', (string) $table, TRUE, 'ipsPad ipsSpacer_top' );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief reactions
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 19 Jan 2018
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\admin\activitystats;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* reactions
|
||||
*/
|
||||
class _reactions extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'reactionsstats_manage' );
|
||||
parent::execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reaction statistics
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
{
|
||||
$tabs = array(
|
||||
'type' => 'stats_reactions_by_type',
|
||||
'app' => 'stats_reactions_by_app',
|
||||
'list' => 'stats_reactions_top_content',
|
||||
'givers' => 'stats_reactions_top_givers',
|
||||
'getters' => 'stats_reactions_top_receivers',
|
||||
);
|
||||
$activeTab = ( isset( \IPS\Request::i()->tab ) and array_key_exists( \IPS\Request::i()->tab, $tabs ) ) ? \IPS\Request::i()->tab : 'type';
|
||||
|
||||
if ( $activeTab === 'type' OR $activeTab === 'app' )
|
||||
{
|
||||
$chart = new \IPS\Helpers\Chart\Database( \IPS\Http\Url::internal( "app=core&module=activitystats&controller=reactions&tab=" . $activeTab ), 'core_reputation_index', 'rep_date', '', array(
|
||||
'isStacked' => FALSE,
|
||||
'backgroundColor' => '#ffffff',
|
||||
'colors' => array( '#10967e', '#ea7963', '#de6470', '#6b9dde', '#b09be4', '#eec766', '#9fc973', '#e291bf', '#55c1a6', '#5fb9da' ),
|
||||
'hAxis' => array( 'gridlines' => array( 'color' => '#f5f5f5' ) ),
|
||||
'lineWidth' => 1,
|
||||
'areaOpacity' => 0.4
|
||||
),
|
||||
'PieChart',
|
||||
'monthly',
|
||||
array( 'start' => 0, 'end' => 0 ),
|
||||
array(),
|
||||
$activeTab
|
||||
);
|
||||
|
||||
if ( $activeTab === 'type' )
|
||||
{
|
||||
$chart->groupBy = 'reaction';
|
||||
|
||||
foreach( \IPS\Content\Reaction::roots() as $reaction )
|
||||
{
|
||||
$chart->addSeries( $reaction->_title, 'number', 'COUNT(*)', TRUE, $reaction->id );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$chart->groupBy = 'app';
|
||||
|
||||
foreach( \IPS\Application::roots() as $app )
|
||||
{
|
||||
$chart->addSeries( $app->_title, 'number', 'COUNT(*)', TRUE, $app->directory );
|
||||
}
|
||||
}
|
||||
|
||||
$chart->availableTypes = array( 'AreaChart', 'ColumnChart', 'BarChart', 'PieChart' );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Database table helpers don't support grouping, so we will manually fetch the results and then let the table helper display */
|
||||
$contentWhere = array();
|
||||
$idToRatingMap = array();
|
||||
|
||||
if( $activeTab == 'list' )
|
||||
{
|
||||
$query = \IPS\Db::i()->select( 'MAX(id) as id, SUM(rep_rating) as rating', 'core_reputation_index', NULL, 'rating DESC', array( 0, 20 ), array( 'app', 'type', 'type_id' ) );
|
||||
}
|
||||
elseif( $activeTab == 'givers' )
|
||||
{
|
||||
$query = \IPS\Db::i()->select( 'MAX(id) as id, SUM(rep_rating) as rating', 'core_reputation_index', NULL, 'rating DESC', array( 0, 20 ), array( 'member_id' ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
$query = \IPS\Db::i()->select( 'MAX(id) as id, SUM(rep_rating) as rating', 'core_reputation_index', NULL, 'rating DESC', array( 0, 20 ), array( 'member_received' ) );
|
||||
}
|
||||
|
||||
foreach( $query as $reputation )
|
||||
{
|
||||
$contentWhere[] = $reputation['id'];
|
||||
$idToRatingMap[ $reputation['id'] ] = $reputation['rating'];
|
||||
}
|
||||
|
||||
/* Create the table */
|
||||
$chart = new \IPS\Helpers\Table\Db( 'core_reputation_index', \IPS\Http\Url::internal( 'app=core&module=activitystats&controller=reactions&type=list' ), array( \IPS\Db::i()->in( 'id', $contentWhere ) ) );
|
||||
$chart->quickSearch = NULL;
|
||||
|
||||
/* Columns we need */
|
||||
if( $activeTab == 'list' )
|
||||
{
|
||||
$chart->langPrefix = 'reactstats_';
|
||||
$chart->include = array( 'type_id', 'rep_date', 'member_id', 'rating' );
|
||||
$chart->mainColumn = 'type_id';
|
||||
}
|
||||
else
|
||||
{
|
||||
$chart->langPrefix = 'reactstatsm_';
|
||||
$column = ( $activeTab == 'givers' ) ? 'member_id' : 'member_received';
|
||||
$chart->include = array( $column, 'rep_date', 'rating' );
|
||||
$chart->mainColumn = $column;
|
||||
}
|
||||
|
||||
$chart->noSort = array( 'member_id', 'type_id', 'rep_date', 'rating' );
|
||||
|
||||
$chart->sortBy = $chart->sortBy ?: 'rating';
|
||||
$chart->sortDirection = $chart->sortDirection ?: 'desc';
|
||||
|
||||
/* Custom parsers */
|
||||
$chart->parsers = array(
|
||||
'rep_date' => function( $val, $row )
|
||||
{
|
||||
return \IPS\DateTime::ts( $val )->localeDate();
|
||||
},
|
||||
'member_id' => function( $val, $row )
|
||||
{
|
||||
return \IPS\Member::load( $val )->link();
|
||||
},
|
||||
'member_received' => function( $val, $row )
|
||||
{
|
||||
return \IPS\Member::load( $val )->link();
|
||||
},
|
||||
'rating' => function( $val, $row ) use ( $idToRatingMap )
|
||||
{
|
||||
/* Return the reputation total */
|
||||
return $idToRatingMap[ $row['id'] ];
|
||||
},
|
||||
'type_id' => function( $val, $row )
|
||||
{
|
||||
$class = $row['rep_class'];
|
||||
|
||||
try
|
||||
{
|
||||
$item = $class::load( $row['type_id'] );
|
||||
|
||||
return \IPS\Theme::i()->getTemplate( 'activitystats' )->contentCell( $item );
|
||||
}
|
||||
catch( \Exception $e )
|
||||
{
|
||||
return \IPS\Member::loggedIn()->language()->addToStack( 'unavailable' );
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->output = (string) $chart;
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__core_activitystats_reactions');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global', 'core' )->tabs( $tabs, $activeTab, (string) $chart, \IPS\Http\Url::internal( "app=core&module=activitystats&controller=reactions" ), 'tab', '', 'ipsPad' );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Tag Usage
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 24 Jan 2018
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\admin\activitystats;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tag Usage
|
||||
*/
|
||||
class _tags extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'tagsusage_manage' );
|
||||
parent::execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a graph of tag usage
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
{
|
||||
$chart = new \IPS\Helpers\Chart\Database( \IPS\Http\Url::internal( "app=core&module=activitystats&controller=tags" ), 'core_tags', 'tag_added', '', array(
|
||||
'isStacked' => FALSE,
|
||||
'backgroundColor' => '#ffffff',
|
||||
'hAxis' => array( 'gridlines' => array( 'color' => '#f5f5f5' ) ),
|
||||
'lineWidth' => 1,
|
||||
'areaOpacity' => 0.4
|
||||
),
|
||||
'AreaChart',
|
||||
'daily',
|
||||
array( 'start' => \IPS\DateTime::create()->sub( new \DateInterval( 'P1M' ) ), 'end' => 0 )
|
||||
);
|
||||
$chart->groupBy = 'tag_text';
|
||||
$chart->availableTypes = array( 'AreaChart', 'ColumnChart', 'BarChart', 'PieChart' );
|
||||
|
||||
$where = $chart->where;
|
||||
$where[] = array( "tag_added>?", 0 );
|
||||
if ( $chart->start )
|
||||
{
|
||||
$where[] = array( "tag_added>?", $chart->start->getTimestamp() );
|
||||
}
|
||||
if ( $chart->end )
|
||||
{
|
||||
$where[] = array( "tag_added<?", $chart->end->getTimestamp() );
|
||||
}
|
||||
|
||||
foreach( \IPS\Db::i()->select( 'tag_text', 'core_tags', $where, NULL, NULL, array( 'tag_text' ) ) as $tag )
|
||||
{
|
||||
$chart->addSeries( $tag, 'number', 'COUNT(*)', TRUE, $tag );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__core_activitystats_tags');
|
||||
\IPS\Output::i()->output = (string) $chart;
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ class _api extends \IPS\Dispatcher\Controller
|
||||
* @return void
|
||||
*/
|
||||
public function __call( $method, $args )
|
||||
{
|
||||
{
|
||||
/* Check htaccess is correct */
|
||||
if ( \IPS\Settings::i()->use_friendly_urls and \IPS\Settings::i()->htaccess_mod_rewrite )
|
||||
{
|
||||
@@ -63,6 +63,10 @@ class _api extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Work out tabs */
|
||||
$tabs = array();
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'applications', 'oauth_manage' ) )
|
||||
{
|
||||
$tabs['oauth'] = 'oauth_clients';
|
||||
}
|
||||
if( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'applications', 'api_manage' ) )
|
||||
{
|
||||
$tabs['apiKeys'] = 'api_keys';
|
||||
@@ -93,30 +97,18 @@ class _api extends \IPS\Dispatcher\Controller
|
||||
$class->execute();
|
||||
|
||||
$output = \IPS\Output::i()->output;
|
||||
|
||||
|
||||
if ( $method !== 'manage' or \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
\IPS\Output::i()->output = '';
|
||||
|
||||
if ( \IPS\Request::i()->isCgi() )
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->message( 'api_url_key_notice', 'information' );
|
||||
}
|
||||
|
||||
/* Help button */
|
||||
\IPS\Output::i()->sidebar['actions']['help'] = array(
|
||||
'icon' => 'question-circle',
|
||||
'title' => 'help',
|
||||
'link' => \IPS\Http\Url::ips( 'docs/restapi' ),
|
||||
'target' => 'blank'
|
||||
);
|
||||
|
||||
|
||||
/* Output */
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'system/api.css', 'core', 'admin' ) );
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'admin_system.js', 'core', 'admin' ) );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__core_applications_api');
|
||||
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'forms', 'core' )->blurb( 'rest_and_oauth_blurb' );
|
||||
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'global', 'core' )->tabs( $tabs, $activeTab, $output, \IPS\Http\Url::internal( "app=core&module=applications&controller=api" ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,11 @@ class _apiKeys extends \IPS\Node\Controller
|
||||
*/
|
||||
public $_descriptionHtml = TRUE;
|
||||
|
||||
/**
|
||||
* Show the "add" button in the page root rather than the table root
|
||||
*/
|
||||
protected $_addButtonInRoot = FALSE;
|
||||
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
@@ -43,4 +48,15 @@ class _apiKeys extends \IPS\Node\Controller
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'system/api.css', 'core', 'admin' ) );
|
||||
parent::execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* View List (checks endpoints are available on https)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'forms', 'core' )->blurb( 'api_keys_blurb', TRUE, TRUE );
|
||||
return parent::manage();
|
||||
}
|
||||
}
|
||||
@@ -57,14 +57,32 @@ class _apiLogs extends \IPS\Dispatcher\Controller
|
||||
},
|
||||
'api_key' => function( $val, $row )
|
||||
{
|
||||
try
|
||||
$apiKey = NULL;
|
||||
$client = NULL;
|
||||
$member = NULL;
|
||||
if ( $row['api_key'] )
|
||||
{
|
||||
return \IPS\Api\Key::load( $val )->_title;
|
||||
try
|
||||
{
|
||||
$apiKey = \IPS\Api\Key::load( $row['api_key'] );
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
if ( $row['client_id'] )
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate('api')->apiKey( $val );
|
||||
try
|
||||
{
|
||||
$client = \IPS\Api\OAuthClient::load( $row['client_id'] );
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
|
||||
if ( $row['member_id'] )
|
||||
{
|
||||
$member = \IPS\Member::load( $row['member_id'] );
|
||||
}
|
||||
}
|
||||
|
||||
return \IPS\Theme::i()->getTemplate('api')->apiLogCredentials( $row, $apiKey, $client, $member );
|
||||
},
|
||||
'response_code' => function( $val )
|
||||
{
|
||||
|
||||
@@ -62,7 +62,7 @@ class _apiReference extends \IPS\Dispatcher\Controller
|
||||
if ( isset( $endpoints[ $selected ]['details']['reqapiparam'] ) )
|
||||
{
|
||||
$params = array_map( function( $v ) {
|
||||
$v[4] = TRUE;
|
||||
$v[4] = 'required';
|
||||
return $v;
|
||||
}, $endpoints[ $selected ]['details']['reqapiparam'] );
|
||||
}
|
||||
@@ -71,6 +71,22 @@ class _apiReference extends \IPS\Dispatcher\Controller
|
||||
$params = array_merge( $params, $endpoints[ $selected ]['details']['apiparam'] );
|
||||
}
|
||||
$exceptions = isset( $endpoints[ $selected ]['details']['throws'] ) ? $endpoints[ $selected ]['details']['throws'] : NULL;
|
||||
if ( isset( $endpoints[ $selected ]['details']['apimemberonly'] ) )
|
||||
{
|
||||
$exceptions[] = array(
|
||||
'3S290/C',
|
||||
'MEMBER_ONLY',
|
||||
\IPS\Member::loggedIn()->language()->addToStack('api_endpoint_member_only_err')
|
||||
);
|
||||
}
|
||||
if ( isset( $endpoints[ $selected ]['details']['apiclientonly'] ) )
|
||||
{
|
||||
$exceptions[] = array(
|
||||
'3S290/D',
|
||||
'CLIENT_ONLY',
|
||||
\IPS\Member::loggedIn()->language()->addToStack('api_endpoint_client_only_err')
|
||||
);
|
||||
}
|
||||
|
||||
$response = NULL;
|
||||
$return = array_filter( $endpoints[ $selected ]['details']['return'][0] );
|
||||
@@ -81,11 +97,11 @@ class _apiReference extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
foreach ( $endpoints[ $selected ]['details']['apiresponse'] as $data )
|
||||
{
|
||||
if ( !in_array( $data[0], array( 'int', 'string', 'float', 'datetime', 'bool', 'object' ) ) )
|
||||
if ( mb_strpos( $data[0], '|' ) === FALSE AND !in_array( $data[0], array( 'int', 'string', 'float', 'datetime', 'bool', 'object', 'array' ) ) )
|
||||
{
|
||||
if ( mb_substr( $data[0], 0, 1 ) == '[' )
|
||||
{
|
||||
if ( !in_array( mb_substr( $data[0], 1, -1 ), array( 'int', 'string', 'float', 'datetime', 'bool', 'object' ) ) )
|
||||
if ( !in_array( mb_substr( $data[0], 1, -1 ), array( 'int', 'string', 'float', 'datetime', 'bool', 'object', 'array' ) ) )
|
||||
{
|
||||
$additionalClassesToReference = array_merge( $additionalClassesToReference, $this->_getAdditionalClasses( mb_substr( $data[0], 1, -1 ) ) );
|
||||
}
|
||||
@@ -126,7 +142,7 @@ class _apiReference extends \IPS\Dispatcher\Controller
|
||||
$decoded = \IPS\Api\Controller::decodeDocblock( $reflection->getDocComment() );
|
||||
$additionalClasses[ mb_strtolower( mb_substr( $class, mb_strrpos( $class, '\\' ) + 1 ) ) ] = \IPS\Theme::i()->getTemplate('api')->referenceTable( $decoded['details']['apiresponse'] );
|
||||
}
|
||||
|
||||
|
||||
$content = \IPS\Theme::i()->getTemplate('api')->referenceEndpoint( $endpoints[ $selected ], $params, $exceptions, $response, $additionalClasses );
|
||||
}
|
||||
|
||||
@@ -160,11 +176,11 @@ class _apiReference extends \IPS\Dispatcher\Controller
|
||||
$decoded = \IPS\Api\Controller::decodeDocblock( $reflection->getDocComment() );
|
||||
foreach ( $decoded['details']['apiresponse'] as $response )
|
||||
{
|
||||
if ( !in_array( $response[0], array( 'int', 'string', 'float', 'datetime', 'bool', 'object' ) ) )
|
||||
if ( mb_strpos( $response[0], '|' ) === FALSE AND !in_array( $response[0], array( 'int', 'string', 'float', 'datetime', 'bool', 'object', 'array' ) ) )
|
||||
{
|
||||
if ( mb_substr( $response[0], 0, 1 ) == '[' )
|
||||
{
|
||||
if ( !in_array( mb_substr( $response[0], 1, -1 ), $return ) and !in_array( mb_substr( $response[0], 1, -1 ), array( 'int', 'string', 'float', 'datetime', 'bool', 'object' ) ) )
|
||||
if ( !in_array( mb_substr( $response[0], 1, -1 ), $return ) and !in_array( mb_substr( $response[0], 1, -1 ), array( 'int', 'string', 'float', 'datetime', 'bool', 'object', 'array' ) ) )
|
||||
{
|
||||
$return = array_merge( $return, $this->_getAdditionalClasses( mb_substr( $response[0], 1, -1 ) ) );
|
||||
}
|
||||
|
||||
@@ -235,7 +235,9 @@ class _applications extends \IPS\Node\Controller
|
||||
*/
|
||||
public function updateCheck()
|
||||
{
|
||||
\IPS\Task::constructFromData( \IPS\Db::i()->select( '*', 'core_tasks', array( 'app=? AND `key`=?', 'core', 'updatecheck' ) )->first() )->run();
|
||||
$task = \IPS\Task::constructFromData( \IPS\Db::i()->select( '*', 'core_tasks', array( 'app=? AND `key`=?', 'core', 'updatecheck' ) )->first() );
|
||||
$task->type = 'manual';
|
||||
$task->run();
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=applications&controller=applications" ), 'update_check_complete' );
|
||||
}
|
||||
|
||||
@@ -629,6 +631,7 @@ class _applications extends \IPS\Node\Controller
|
||||
}
|
||||
catch( \PharException $e )
|
||||
{
|
||||
\IPS\Log::log( $e, 'phar' );
|
||||
\IPS\Output::i()->error( 'app_no_phar', '4C133/7', 403, '' );
|
||||
}
|
||||
|
||||
@@ -1242,7 +1245,7 @@ class _applications extends \IPS\Node\Controller
|
||||
|
||||
/* Work out tab */
|
||||
$tab = \IPS\Request::i()->tab ?: 'details';
|
||||
$activeTabContents = call_user_func( array( $this, '_show' . ucfirst( $tab ) ), $application );
|
||||
$activeTabContents = call_user_func( array( $this, '_show' . mb_ucfirst( $tab ) ), $application );
|
||||
|
||||
/* If this is an AJAX request, just return tab contents */
|
||||
if( \IPS\Request::i()->isAjax() && \IPS\Request::i()->tab and !isset( \IPS\Request::i()->ajaxValidate ) )
|
||||
@@ -1376,6 +1379,7 @@ class _applications extends \IPS\Node\Controller
|
||||
}
|
||||
catch( \PharException $e )
|
||||
{
|
||||
\IPS\Log::log( $e, 'phar' );
|
||||
\IPS\Output::i()->error( 'application_notvalid', '1C133/9', 403, '' );
|
||||
}
|
||||
catch( \UnexpectedValueException $e )
|
||||
@@ -1413,7 +1417,8 @@ class _applications extends \IPS\Node\Controller
|
||||
}
|
||||
else
|
||||
{
|
||||
@chmod( $f->getPathname(), \IPS\IPS_FILE_PERMISSION );
|
||||
/* If this is a .php file in the /interface/ folder it will be called via web directly. We cannot set permissions too high though or it won't execute in many environments */
|
||||
@chmod( $f->getPathname(), ( mb_strpos( $f->getPathname(), '/interface/' ) !== FALSE AND mb_strtolower( $f->getExtension() ) == 'php' ) ? \IPS\FILE_PERMISSION_NO_WRITE : \IPS\IPS_FILE_PERMISSION );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1546,20 +1551,4 @@ class _applications extends \IPS\Node\Controller
|
||||
|
||||
return $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle Enabled/Disable
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function enableToggle()
|
||||
{
|
||||
/* Clear templates to rebuild automatically */
|
||||
\IPS\Theme::deleteCompiledTemplate();
|
||||
|
||||
/* Invalidate disk templates */
|
||||
\IPS\Theme::resetAllCacheKeys();
|
||||
|
||||
parent::enableToggle();
|
||||
}
|
||||
}
|
||||
@@ -80,11 +80,11 @@ class _developer extends \IPS\Dispatcher\Controller
|
||||
/* Work out output */
|
||||
if ( $pos = mb_strpos( $this->activeTab, '-' ) )
|
||||
{
|
||||
$activeTabContents = call_user_func( array( $this, '_manage'.ucfirst( mb_substr( $this->activeTab, 0, $pos ) ) ), mb_substr( $this->activeTab, $pos + 1 ) );
|
||||
$activeTabContents = call_user_func( array( $this, '_manage' . mb_ucfirst( mb_substr( $this->activeTab, 0, $pos ) ) ), mb_substr( $this->activeTab, $pos + 1 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
$activeTabContents = call_user_func( array( $this, '_manage'.ucfirst( $this->activeTab ) ) );
|
||||
$activeTabContents = call_user_func( array( $this, '_manage' . mb_ucfirst( $this->activeTab ) ) );
|
||||
}
|
||||
|
||||
/* If this is an AJAX request, just return it */
|
||||
@@ -483,6 +483,9 @@ class _developer extends \IPS\Dispatcher\Controller
|
||||
$position = array();
|
||||
foreach( \IPS\Request::i()->ajax_order as $id => $parent )
|
||||
{
|
||||
/* We have to fudge children "ids" to prevent conflicts in the array */
|
||||
$id = str_replace( 's@', '', $id );
|
||||
|
||||
if ( !isset( $order[ $parent ] ) )
|
||||
{
|
||||
$order[ $parent ] = array();
|
||||
@@ -496,13 +499,30 @@ class _developer extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$order = array( \IPS\Request::i()->root ?: 'null' => \IPS\Request::i()->order );
|
||||
}
|
||||
|
||||
|
||||
/* Sort */
|
||||
$_menu = $menu;
|
||||
$menu = $menu;
|
||||
$menu = array();
|
||||
|
||||
if( isset( $order['null'] ) )
|
||||
{
|
||||
foreach( $order['null'] as $key => $position )
|
||||
{
|
||||
foreach ( $_menu as $_parent => $_items )
|
||||
{
|
||||
if ( $key == $_parent )
|
||||
{
|
||||
$menu[ $_parent ] = $_menu[ $_parent ];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach ( $order as $parent => $items )
|
||||
{
|
||||
if ( array_key_exists( $parent, $menu ) )
|
||||
if ( $parent === NULL OR array_key_exists( $parent, $_menu ) )
|
||||
{
|
||||
$menu[ $parent ] = array();
|
||||
foreach ( $items as $key => $position )
|
||||
@@ -511,7 +531,7 @@ class _developer extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
if ( array_key_exists( $key, $_items ) )
|
||||
{
|
||||
$menu[ $parent ][ $key ] = $_menu[ $_parent ][ $key ];
|
||||
$menu[ $parent ][ $key ] = $_menu[ $_parent ][ $key ];
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -576,7 +596,7 @@ class _developer extends \IPS\Dispatcher\Controller
|
||||
foreach ( $menu[ $k ] as $id => $row )
|
||||
{
|
||||
$lang = "menu__{$appKey}_{$k}_{$id}";
|
||||
$rows[ $id ] = \IPS\Theme::i()->getTemplate( 'trees' )->row( $url, $id, \IPS\Member::loggedIn()->language()->addToStack( $lang ), FALSE, array(
|
||||
$rows[ 's@' . $id ] = \IPS\Theme::i()->getTemplate( 'trees' )->row( $url, 's@' . $id, \IPS\Member::loggedIn()->language()->addToStack( $lang ), FALSE, array(
|
||||
'edit' => array(
|
||||
'icon' => 'pencil',
|
||||
'title' => 'edit',
|
||||
@@ -608,7 +628,7 @@ class _developer extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function menuForm()
|
||||
{
|
||||
/* Current Manu */
|
||||
/* Current Menu */
|
||||
$menu = $this->_getJson( \IPS\ROOT_PATH . "/applications/{$this->application->directory}/data/acpmenu.json" );
|
||||
|
||||
/* Get module and controllers */
|
||||
@@ -723,7 +743,7 @@ class _developer extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Sort */
|
||||
uasort( $this->restrictions[ $id[0] ][ $id[1] ], function( $a, $b ) use ( $order ) {
|
||||
return $order[ str_replace( '_', '~', $a ) ] - $order[ str_replace( '_', '~', $b ) ];
|
||||
return ( isset( $order[ str_replace( '_', '~', $a ) ] ) ? $order[ str_replace( '_', '~', $a ) ] : 0 ) - ( isset( $order[ str_replace( '_', '~', $b ) ] ) ? $order[ str_replace( '_', '~', $b ) ] : 0 );
|
||||
});
|
||||
|
||||
/* Write */
|
||||
@@ -1103,7 +1123,7 @@ class _developer extends \IPS\Dispatcher\Controller
|
||||
isset( $values['model_name'] ) ? $values['model_name'] : NULL,
|
||||
isset( $values['database_table_name'] ) ? $values['database_table_name'] : NULL,
|
||||
),
|
||||
file_get_contents( \IPS\ROOT_PATH . "/applications/core/data/defaults/Controller" . ucfirst( $values['type'] ) . '.txt' )
|
||||
file_get_contents( \IPS\ROOT_PATH . "/applications/core/data/defaults/Controller" . mb_ucfirst( $values['type'] ) . '.txt' )
|
||||
);
|
||||
|
||||
/* If this isn't an IPS app, strip out our header */
|
||||
@@ -1125,7 +1145,7 @@ class _developer extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$menu = $this->_getJson( \IPS\ROOT_PATH . "/applications/{$this->application->directory}/data/acpmenu.json" );
|
||||
$menu[ $module->key ][ $values['filename'] ] = array(
|
||||
'tab' => $values['acpmenu_tab'][0],
|
||||
'tab' => $values['acpmenu_tab'],
|
||||
'controller' => $values['filename'],
|
||||
'do' => '',
|
||||
'restriction' => $restriction
|
||||
@@ -1496,6 +1516,7 @@ class _developer extends \IPS\Dispatcher\Controller
|
||||
unset( $_definition['comment'] );
|
||||
unset( $_definition['engine'] );
|
||||
unset( $_definition['collation'] );
|
||||
unset( $_definition['reporting'] );
|
||||
try
|
||||
{
|
||||
$localDefinition = $this->_getTableDefinition( $definition['name'] );
|
||||
@@ -1605,6 +1626,14 @@ class _developer extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
) );
|
||||
|
||||
if ( in_array( $this->application->directory, \IPS\Application::$ipsApps ) )
|
||||
{
|
||||
$output->add( new \IPS\Helpers\Form\Select( 'database_table_reporting', isset( $definition['reporting'] ) ? $definition['reporting'] : 'none', FALSE, array( 'options' => array(
|
||||
'none' => 'database_table_reporting_none',
|
||||
'count' => 'database_table_reporting_count',
|
||||
) ) ) );
|
||||
}
|
||||
|
||||
/* Handle submissions */
|
||||
if ( $values = $output->values() )
|
||||
{
|
||||
@@ -1628,6 +1657,12 @@ class _developer extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
/* Changed reporting? */
|
||||
if ( !isset( $definition['reporting'] ) or $values['database_table_reporting'] !== $definition['reporting'] )
|
||||
{
|
||||
$schemaJson[ $definition['name'] ]['reporting'] = $values['database_table_reporting'];
|
||||
}
|
||||
|
||||
/* Renamed table? */
|
||||
$values['database_table_name'] = "{$this->application->directory}_{$values['database_table_name']}";
|
||||
if ( $values['database_table_name'] !== $definition['name'] )
|
||||
@@ -1639,7 +1674,7 @@ class _developer extends \IPS\Dispatcher\Controller
|
||||
unset( $schemaJson[ $definition['name'] ] );
|
||||
$definition['name'] = $values['database_table_name'];
|
||||
}
|
||||
|
||||
|
||||
/* Run queries */
|
||||
foreach ( $queries as $query )
|
||||
{
|
||||
@@ -2487,7 +2522,7 @@ class _developer extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Use local database */
|
||||
if ( \IPS\Request::i()->local )
|
||||
{
|
||||
{
|
||||
foreach ( $localDefinition['columns'] as $i => $data )
|
||||
{
|
||||
if ( $data['type'] == 'BIT' )
|
||||
@@ -2500,6 +2535,14 @@ class _developer extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$schema[ \IPS\Request::i()->_name ]['inserts'] = $schemaDefinition['inserts'];
|
||||
}
|
||||
if ( isset( $schemaDefinition['engine'] ) )
|
||||
{
|
||||
$schema[ \IPS\Request::i()->_name ]['engine'] = $schemaDefinition['engine'];
|
||||
}
|
||||
else
|
||||
{
|
||||
unset( $schema[ \IPS\Request::i()->_name ]['engine'] );
|
||||
}
|
||||
$this->_writeSchema( $schema );
|
||||
}
|
||||
/* Use schema file */
|
||||
@@ -2755,8 +2798,16 @@ class _developer extends \IPS\Dispatcher\Controller
|
||||
$form->langPrefix = 'dev_settings_';
|
||||
$form->columns = array(
|
||||
'key' => array( 'Text', NULL, TRUE ),
|
||||
'default' => array( 'Text' )
|
||||
'default' => array( 'Text' ),
|
||||
);
|
||||
if ( in_array( $this->application->directory, \IPS\Application::$ipsApps ) )
|
||||
{
|
||||
$form->columns['report'] = array( 'Select', 'none', FALSE, array( 'options' => array(
|
||||
'none' => 'dev_settings_none',
|
||||
'full' => 'dev_settings_full',
|
||||
'bool' => 'dev_settings_bool',
|
||||
) ) );
|
||||
}
|
||||
$form->rows = $settings;
|
||||
|
||||
if ( $form->values() !== FALSE )
|
||||
@@ -2804,7 +2855,7 @@ class _developer extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
return strnatcmp( $a['key'], $b['key'] );
|
||||
} );
|
||||
|
||||
|
||||
$this->_writeJson( \IPS\ROOT_PATH . "/applications/{$this->application->directory}/data/settings.json", $save );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=applications&controller=developer&appKey={$this->application->directory}&tab=settings" ) );
|
||||
}
|
||||
@@ -3694,6 +3745,21 @@ class _developer extends \IPS\Dispatcher\Controller
|
||||
case 'changeColumn':
|
||||
unset( $queriesJson[ $i ]['params'][0]['columns'][ $query['params'][1] ] );
|
||||
$queriesJson[ $i ]['params'][0]['columns'][ $query['params'][2]['name'] ] = $query['params'][2];
|
||||
|
||||
/* Fix references to the column name in indexes */
|
||||
if ( isset( $queriesJson[ $i ]['params'][0]['indexes'] ) )
|
||||
{
|
||||
foreach( $queriesJson[ $i ]['params'][0]['indexes'] as $indexName => $indexDefinition )
|
||||
{
|
||||
foreach( $indexDefinition['columns'] as $_idx => $columnName )
|
||||
{
|
||||
if( $columnName == $query['params'][1] )
|
||||
{
|
||||
$queriesJson[ $i ]['params'][0]['indexes'][ $indexName ]['columns'][ $_idx ] = $query['params'][2]['name'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$added = TRUE;
|
||||
break;
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ class _menu extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
if ( !$field->htmlId )
|
||||
{
|
||||
$field->htmlId = md5( uniqid() );
|
||||
$field->htmlId = md5( mt_rand() );
|
||||
}
|
||||
|
||||
$toggles[ $key ][ $field->name ] = $field->htmlId;
|
||||
|
||||
@@ -0,0 +1,430 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief OAuth Clients
|
||||
* @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 29 Apr 2017
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\admin\applications;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* OAuth Clients
|
||||
*/
|
||||
class _oauth extends \IPS\Node\Controller
|
||||
{
|
||||
/**
|
||||
* Node Class
|
||||
*/
|
||||
protected $nodeClass = 'IPS\Api\OAuthClient';
|
||||
|
||||
/**
|
||||
* Show the "add" button in the page root rather than the table root
|
||||
*/
|
||||
protected $_addButtonInRoot = FALSE;
|
||||
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'oauth_manage' );
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'system/api.css', 'core', 'admin' ) );
|
||||
return parent::execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* View List (checks endpoints are available on https)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
{
|
||||
if ( \IPS\OAUTH_REQUIRES_HTTPS and mb_substr( \IPS\Settings::i()->base_url, 0, 8 ) !== 'https://' )
|
||||
{
|
||||
try
|
||||
{
|
||||
$response = \IPS\Http\Url::external( 'https://' . mb_substr( \IPS\Settings::i()->base_url, 7 ) )->request()->get();
|
||||
}
|
||||
catch ( \IPS\Http\Request\Exception $e )
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'forms' )->blurb( \IPS\CIC ? 'oauth_https_warning_cic' : 'oauth_https_warning', TRUE, TRUE );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'forms', 'core' )->blurb( 'oauth_clients_blurb', TRUE, TRUE );
|
||||
return parent::manage();
|
||||
}
|
||||
|
||||
/**
|
||||
* View Client Details
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function view()
|
||||
{
|
||||
try
|
||||
{
|
||||
$client = \IPS\Api\OAuthClient::load( \IPS\Request::i()->client_id );
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C362/1', 404, '' );
|
||||
}
|
||||
|
||||
$secret = NULL;
|
||||
if ( isset( \IPS\Request::i()->newSecret ) and \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'applications', 'oauth_secrets' ) )
|
||||
{
|
||||
$secret = \IPS\Login::generateRandomString( 48 );
|
||||
$client->client_secret = password_hash( $secret, PASSWORD_DEFAULT );
|
||||
$client->brute_force = NULL;
|
||||
$client->save();
|
||||
|
||||
\IPS\Session::i()->log( 'acplogs__oauth_new_secret', array( 'core_oauth_client_' . $client->client_id => TRUE ) );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->sidebar['actions'] = $client->getButtons( \IPS\Http\Url::internal( "app=core&module=applications&controller=oauth&do=view&client_id={$client->client_id}" ) );
|
||||
unset( \IPS\Output::i()->sidebar['actions']['view'] );
|
||||
|
||||
$bruteForce = NULL;
|
||||
if ( $client->brute_force and $bruteForce = json_decode( $client->brute_force, TRUE ) )
|
||||
{
|
||||
$data = array();
|
||||
foreach ( $bruteForce as $ipAddress => $fails )
|
||||
{
|
||||
$data[] = array(
|
||||
'ip_address' => $ipAddress,
|
||||
'fails' => $fails
|
||||
);
|
||||
}
|
||||
|
||||
$bruteForce = new \IPS\Helpers\Table\Custom( $data, \IPS\Http\Url::internal( "app=core&module=applications&controller=oauth&do=view&client_id={$client->client_id}" ) );
|
||||
$bruteForce->langPrefix = 'oauth_brute_force_';
|
||||
$bruteForce->rowButtons = function( $row ) use ( $client ) {
|
||||
$return = array();
|
||||
$return['ban'] = array(
|
||||
'icon' => 'ban',
|
||||
'title' => 'oauth_brute_force_ban',
|
||||
'link' => \IPS\Http\Url::internal( "app=core&module=applications&controller=oauth&do=bfRemove&ban=1&client_id={$client->client_id}" )->setQueryString( 'ip', $row['ip_address'] )
|
||||
);
|
||||
if ( $row['fails'] >= 3 )
|
||||
{
|
||||
$return['unlock'] = array(
|
||||
'icon' => 'unlock',
|
||||
'title' => 'oauth_brute_force_unlock',
|
||||
'link' => \IPS\Http\Url::internal( "app=core&module=applications&controller=oauth&do=bfRemove&client_id={$client->client_id}" )->setQueryString( 'ip', $row['ip_address'] )
|
||||
);
|
||||
}
|
||||
return $return;
|
||||
};
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = $client->_title;
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('api')->oauthSecret( $client, $secret, $bruteForce );
|
||||
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( "app=core&module=applications&controller=api&tab=oauth" ), 'oauth_clients' );
|
||||
\IPS\Output::i()->breadcrumb[] = array( NULL, $client->_title );
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove IP Address from bruteforce
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function bfRemove()
|
||||
{
|
||||
try
|
||||
{
|
||||
$client = \IPS\Api\OAuthClient::load( \IPS\Request::i()->client_id );
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C362/4', 404, '' );
|
||||
}
|
||||
|
||||
if ( \IPS\Request::i()->ip and \IPS\Request::i()->ban )
|
||||
{
|
||||
\IPS\Db::i()->insert( 'core_banfilters', array(
|
||||
'ban_type' => 'ip',
|
||||
'ban_content' => \IPS\Request::i()->ip,
|
||||
'ban_date' => time(),
|
||||
'ban_reason' => 'OAuth',
|
||||
) );
|
||||
unset( \IPS\Data\Store::i()->bannedIpAddresses );
|
||||
\IPS\Session::i()->log( 'acplog__ban_created', array( 'ban_filter_ip_select' => TRUE, \IPS\Request::i()->ip => FALSE ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Session::i()->log( 'acplogs__oauth_unlock_ip', array( \IPS\Request::i()->ip => FALSE, 'core_oauth_client_' . $client->client_id => TRUE ) );
|
||||
}
|
||||
|
||||
$bruteForce = json_decode( $client->brute_force, TRUE );
|
||||
unset( $bruteForce[ \IPS\Request::i()->ip ] );
|
||||
$client->brute_force = json_encode( $bruteForce );
|
||||
$client->save();
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=applications&controller=oauth&do=view&client_id={$client->client_id}" ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* View Authorizations
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function tokens()
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'oauth_tokens' );
|
||||
|
||||
$client = NULL;
|
||||
$member = NULL;
|
||||
try
|
||||
{
|
||||
if ( isset( \IPS\Request::i()->client_id ) )
|
||||
{
|
||||
$client = \IPS\Api\OAuthClient::load( \IPS\Request::i()->client_id );
|
||||
$baseUrl = \IPS\Http\Url::internal( "app=core&module=applications&controller=oauth&do=tokens&client_id={$client->client_id}" );
|
||||
}
|
||||
else
|
||||
{
|
||||
$member = \IPS\Member::load( \IPS\Request::i()->member_id );
|
||||
if ( !$member->member_id )
|
||||
{
|
||||
throw new \OutOfRangeException;
|
||||
}
|
||||
$baseUrl = \IPS\Http\Url::internal( "app=core&module=applications&controller=oauth&do=tokens&member_id={$member->member_id}" );
|
||||
}
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C362/3', 404, '' );
|
||||
}
|
||||
|
||||
$table = new \IPS\Helpers\Table\Db( 'core_oauth_server_access_tokens', $baseUrl, array( $client ? array( 'client_id=?', $client->client_id ) : array( 'member_id=?', $member->member_id ) ) );
|
||||
$table->langPrefix = 'oauth_authorization_';
|
||||
$table->include = array();
|
||||
$table->advancedSearch = array();
|
||||
if ( $client )
|
||||
{
|
||||
$table->include[] = 'member_id';
|
||||
$table->advancedSearch['member_id'] = \IPS\Helpers\Table\SEARCH_MEMBER;
|
||||
}
|
||||
else
|
||||
{
|
||||
$table->include[] = 'client_id';
|
||||
}
|
||||
$table->include[] = 'issued';
|
||||
$table->include[] = 'status';
|
||||
$table->advancedSearch['issued'] = \IPS\Helpers\Table\SEARCH_DATE_RANGE;
|
||||
if ( !$client or $client->access_token_length )
|
||||
{
|
||||
$table->include[] = 'access_token_expires';
|
||||
$table->advancedSearch['access_token_expires'] = \IPS\Helpers\Table\SEARCH_DATE_RANGE;
|
||||
}
|
||||
if ( !$client or ( $client->use_refresh_tokens and $client->refresh_token_length ) )
|
||||
{
|
||||
$table->include[] = 'refresh_token_expires';
|
||||
$table->advancedSearch['refresh_token_expires'] = \IPS\Helpers\Table\SEARCH_DATE_RANGE;
|
||||
}
|
||||
if ( !$client or ( $client->scopes and json_decode( $client->scopes ) ) )
|
||||
{
|
||||
$table->include[] = 'scope';
|
||||
}
|
||||
$table->noSort = array( 'status', 'scope' );
|
||||
$table->sortBy = $table->sortBy ?: 'issued';
|
||||
$table->parsers = array(
|
||||
'client_id' => function( $val ) {
|
||||
try
|
||||
{
|
||||
$client = \IPS\Api\OAuthClient::load( $val );
|
||||
return \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->basicUrl( \IPS\Http\Url::internal( "app=core&module=applications&controller=oauth&do=view&client_id={$client->client_id}" ), FALSE, $client->_title, FALSE );
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
return '';
|
||||
}
|
||||
},
|
||||
'member_id' => function( $val ) {
|
||||
if ( $val )
|
||||
{
|
||||
$member = \IPS\Member::load( $val );
|
||||
if ( $member->member_id )
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate( 'global', 'core' )->userPhoto( $member, 'tiny' ) . \IPS\Theme::i()->getTemplate( 'global', 'core' )->userLink( $member, 'tiny' );
|
||||
}
|
||||
else
|
||||
{
|
||||
return \IPS\Member::loggedIn()->language()->addToStack('deleted_member');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return \IPS\Member::loggedIn()->language()->addToStack('oauth_client_credentials');
|
||||
}
|
||||
},
|
||||
'issued' => function( $val ) {
|
||||
return \IPS\DateTime::ts( $val );
|
||||
},
|
||||
'access_token_expires' => function( $val ) {
|
||||
if ( $val )
|
||||
{
|
||||
return \IPS\DateTime::ts( $val );
|
||||
}
|
||||
else
|
||||
{
|
||||
return \IPS\Member::loggedIn()->language()->addToStack('never');
|
||||
}
|
||||
},
|
||||
'refresh_token_expires' => function( $val, $row ) {
|
||||
if ( \IPS\Api\OAuthClient::load( $row['client_id'] )->use_refresh_tokens )
|
||||
{
|
||||
if ( $val )
|
||||
{
|
||||
return \IPS\DateTime::ts( $val );
|
||||
}
|
||||
else
|
||||
{
|
||||
return \IPS\Member::loggedIn()->language()->addToStack('never');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return '';
|
||||
}
|
||||
},
|
||||
'status' => function( $val, $row ) {
|
||||
return \IPS\Theme::i()->getTemplate('api')->oauthStatus( $row, \IPS\Api\OAuthClient::load( $row['client_id'] )->use_refresh_tokens );
|
||||
},
|
||||
'scope' => function( $val ) {
|
||||
if ( $val )
|
||||
{
|
||||
return implode( '<br>', json_decode( $val ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return '';
|
||||
}
|
||||
}
|
||||
);
|
||||
$table->rowButtons = function( $row ) use ( $client ) {
|
||||
return array(
|
||||
'revoke' => array(
|
||||
'icon' => 'times-circle',
|
||||
'title' => 'oauth_app_revoke',
|
||||
'link' => \IPS\Http\Url::internal( "app=core&module=applications&controller=oauth&do=revokeToken&client_id={$row['client_id']}&member_id={$row['member_id']}&token={$row['access_token']}" )->setQueryString( 'r', $client ? 'c' : 'm' ),
|
||||
'data' => array( 'delete' => '' )
|
||||
)
|
||||
);
|
||||
};
|
||||
$revokeAllLink = $client ? \IPS\Http\Url::internal( "app=core&module=applications&controller=oauth&do=revokeAllTokens&client_id={$client->client_id}" ) : \IPS\Http\Url::internal( "app=core&module=applications&controller=oauth&do=revokeAllTokens&member_id={$member->member_id}" );
|
||||
$table->rootButtons = array(
|
||||
'revoke' => array(
|
||||
'icon' => 'times-circle',
|
||||
'title' => 'oauth_revoke_all_tokens',
|
||||
'link' => $revokeAllLink,
|
||||
'data' => array( 'confirm' => '' )
|
||||
)
|
||||
);
|
||||
|
||||
\IPS\Output::i()->output = $table;
|
||||
if ( $client )
|
||||
{
|
||||
\IPS\Output::i()->title = $client->_title;
|
||||
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( "app=core&module=applications&controller=api&tab=oauth" ), 'oauth_clients' );
|
||||
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( "app=core&module=applications&controller=oauth&do=view&client_id={$client->client_id}" ), $client->_title );
|
||||
\IPS\Output::i()->breadcrumb[] = array( NULL, 'oauth_view_authorizations' );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->title = $member->name;
|
||||
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( "app=core&module=members&controller=members&do=edit&id={$member->member_id}" ), $member->name );
|
||||
\IPS\Output::i()->breadcrumb[] = array( NULL, 'oauth_member_authorizations' );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Revoke Authorizations
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function revokeToken()
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'oauth_tokens' );
|
||||
|
||||
\IPS\Db::i()->delete( 'core_oauth_server_access_tokens', array( 'client_id=? AND access_token=?', \IPS\Request::i()->client_id, \IPS\Request::i()->token ) );
|
||||
\IPS\Session::i()->log( 'acplogs__oauth_revoke_token', array( 'core_oauth_client_' . \IPS\Request::i()->client_id => TRUE ) );
|
||||
|
||||
if ( \IPS\Request::i()->r === 'c' )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=applications&controller=oauth&do=tokens" )->setQueryString( 'client_id', \IPS\Request::i()->client_id ) );
|
||||
}
|
||||
elseif ( \IPS\Request::i()->r === 'p' )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=members&controller=members&do=view" )->setQueryString( 'id', \IPS\Request::i()->client_id ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=applications&controller=oauth&do=tokens" )->setQueryString( 'member_id', \IPS\Request::i()->member_id ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Revoke ALL Authorizations
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function revokeAllTokens()
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'oauth_tokens' );
|
||||
|
||||
if ( \IPS\Request::i()->member_id )
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_oauth_server_access_tokens', array( 'member_id=?', \IPS\Request::i()->member_id ) );
|
||||
\IPS\Session::i()->log( 'acplogs__oauth_revoke_member', array( \IPS\Member::load( \IPS\Request::i()->member_id )->name => FALSE ) );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=applications&controller=oauth&do=tokens" )->setQueryString( 'member_id', \IPS\Request::i()->member_id ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_oauth_server_access_tokens', array( 'client_id=?', \IPS\Request::i()->client_id ) );
|
||||
\IPS\Session::i()->log( 'acplogs__oauth_revoke_client', array( 'core_oauth_client_' . $client->client_id => TRUE ) );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=applications&controller=oauth&do=tokens" )->setQueryString( 'client_id', \IPS\Request::i()->client_id ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect after save
|
||||
*
|
||||
* @param \IPS\Node\Model $old A clone of the node as it was before or NULL if this is a creation
|
||||
* @param \IPS\Node\Model $new The node now
|
||||
* @param string $lastUsedTab The tab last used in the form
|
||||
* @return void
|
||||
*/
|
||||
protected function _afterSave( \IPS\Node\Model $old = NULL, \IPS\Node\Model $new, $lastUsedTab = FALSE )
|
||||
{
|
||||
if ( $new->_clientSecret )
|
||||
{
|
||||
\IPS\Output::i()->title = $new->_title;
|
||||
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( "app=core&module=applications&controller=api&tab=oauth" ), 'oauth_clients' );
|
||||
\IPS\Output::i()->breadcrumb[] = array( NULL, $new->_title );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('api')->oauthSecret( $new, $new->_clientSecret, NULL );
|
||||
\IPS\Output::i()->sidebar['actions'] = $new->getButtons( \IPS\Http\Url::internal( "app=core&module=applications&controller=oauth&do=view&client_id={$new->client_id}" ) );
|
||||
unset( \IPS\Output::i()->sidebar['actions']['view'] );
|
||||
}
|
||||
else
|
||||
{
|
||||
return parent::_afterSave( $old, $new, $lastUsedTab );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 25 Jul 2013␍
|
||||
* @since 25 Jul 2013
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\admin\applications;
|
||||
@@ -84,10 +84,8 @@ class _plugins extends \IPS\Node\Controller
|
||||
$disabledPlugins[] = $plugin->id;
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Settings::i()->disable_all_plugins = implode( ',', $disabledPlugins );
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => \IPS\Settings::i()->disable_all_plugins ), array( 'conf_key=?', 'disable_all_plugins' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
|
||||
\IPS\Settings::i()->changeValues( array( 'disable_all_plugins' => implode( ',', $disabledPlugins ) ) );
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=applications&controller=plugins' ) );
|
||||
}
|
||||
@@ -110,10 +108,8 @@ class _plugins extends \IPS\Node\Controller
|
||||
}
|
||||
catch ( \Exception $e ) {}
|
||||
}
|
||||
|
||||
\IPS\Settings::i()->disable_all_plugins = '';
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => '' ), array( 'conf_key=?', 'disable_all_plugins' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
|
||||
\IPS\Settings::i()->changeValues( array( 'disable_all_plugins' => '' ) );
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=applications&controller=plugins' ) );
|
||||
}
|
||||
@@ -295,7 +291,7 @@ class _plugins extends \IPS\Node\Controller
|
||||
if ( !$plugin->location )
|
||||
{
|
||||
$directory = \mb_strtolower( preg_replace( '#[^a-zA-Z0-9_]#', '', $plugin->name ) );
|
||||
$plugin->location = file_exists( \IPS\ROOT_PATH . "/plugins/" . $directory ) ? 'p' . mb_substr( md5( uniqid() ), 0, 10 ) : $directory;
|
||||
$plugin->location = file_exists( \IPS\ROOT_PATH . "/plugins/" . $directory ) ? 'p' . mb_substr( md5( mt_rand() ), 0, 10 ) : $directory;
|
||||
}
|
||||
|
||||
$plugin->version_long = $xml->getAttribute('version_long');
|
||||
@@ -380,7 +376,7 @@ class _plugins extends \IPS\Node\Controller
|
||||
while ( $xml->read() and $xml->name == 'hook' )
|
||||
{
|
||||
/* Make up a filename */
|
||||
$filename = $xml->getAttribute( 'filename' ) ?: md5( uniqid() . mt_rand() );
|
||||
$filename = $xml->getAttribute( 'filename' ) ?: md5( mt_rand() );
|
||||
|
||||
/* Insert into DB */
|
||||
$insertId = \IPS\Db::i()->insert( 'core_hooks', array( 'plugin' => $plugin->id, 'type' => $xml->getAttribute('type'), 'class' => $xml->getAttribute('class'), 'filename' => $filename ) );
|
||||
@@ -444,7 +440,7 @@ class _plugins extends \IPS\Node\Controller
|
||||
\IPS\Db::i()->insert( 'core_sys_conf_settings', $inserts , TRUE );
|
||||
}
|
||||
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
\IPS\Settings::i()->clearCache();
|
||||
break;
|
||||
|
||||
/* Settings code */
|
||||
@@ -1001,7 +997,7 @@ class _plugins extends \IPS\Node\Controller
|
||||
|
||||
/* Get tab contents */
|
||||
$activeTab = \IPS\Request::i()->tab ?: 'hooks';
|
||||
$activeTabContents = call_user_func( array( $this, '_manage'.ucfirst( $activeTab ) ), $plugin );
|
||||
$activeTabContents = call_user_func( array( $this, '_manage' . mb_ucfirst( $activeTab ) ), $plugin );
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->output = $activeTabContents;
|
||||
@@ -1111,7 +1107,7 @@ class _plugins extends \IPS\Node\Controller
|
||||
/* Fix if/foreach/for tags...htmlspecialchars the content in case there is a -> which will break things */
|
||||
$code = preg_replace_callback( '/\{\{(if|foreach|for)\s+?(.+?)\}\}/i', function( $matches )
|
||||
{
|
||||
return '<' . $matches[1] . ' code="' . htmlspecialchars( $matches[2], \IPS\HTMLENTITIES | ENT_QUOTES, 'UTF-8', FALSE ) . '">';
|
||||
return '<' . $matches[1] . ' code="' . htmlspecialchars( $matches[2], ENT_DISALLOWED | ENT_QUOTES, 'UTF-8', FALSE ) . '">';
|
||||
}, $code );
|
||||
|
||||
/* Fix ending if/foreach/for tags */
|
||||
@@ -1120,7 +1116,7 @@ class _plugins extends \IPS\Node\Controller
|
||||
/* Fix regular template tags such as url to htmlspecialchars the content */
|
||||
$code = preg_replace_callback( '/\{([a-z]+?=([\'"]).+?\\2 ?+)}/', function( $matches )
|
||||
{
|
||||
return htmlspecialchars( $matches[0], \IPS\HTMLENTITIES | ENT_QUOTES, 'UTF-8', FALSE );
|
||||
return htmlspecialchars( $matches[0], ENT_DISALLOWED | ENT_QUOTES, 'UTF-8', FALSE );
|
||||
}, $code );
|
||||
|
||||
/* Strip any raw replacement tags remaining */
|
||||
@@ -1136,7 +1132,7 @@ class _plugins extends \IPS\Node\Controller
|
||||
}
|
||||
|
||||
/* Fix embedded single quotes */
|
||||
$code = preg_replace_callback( '/=\'([^\']+?){.+?}([^\']+?)\'/', function( $matches )
|
||||
$code = preg_replace_callback( '/=\'([^\']*?){.+?}([^\']*?)\'/', function( $matches )
|
||||
{
|
||||
return "=''";
|
||||
}, $code );
|
||||
@@ -1144,7 +1140,7 @@ class _plugins extends \IPS\Node\Controller
|
||||
/* Ensure attributes with variable data are encoded before the cheeky DOM parser gets to it */
|
||||
$code = preg_replace_callback( '/=([\'"])(\{.+?\})([\'"])/', function( $matches )
|
||||
{
|
||||
return "=" . $matches[1] . htmlspecialchars( $matches[2], \IPS\HTMLENTITIES | ENT_QUOTES, 'UTF-8', FALSE ) . $matches[3];
|
||||
return "=" . $matches[1] . htmlspecialchars( $matches[2], ENT_DISALLOWED | ENT_QUOTES, 'UTF-8', FALSE ) . $matches[3];
|
||||
}, $code );
|
||||
|
||||
/* Now load the HTML - doctype necessary sometimes */
|
||||
@@ -1156,7 +1152,7 @@ class _plugins extends \IPS\Node\Controller
|
||||
/**
|
||||
* Get the CSS selector for a node
|
||||
*
|
||||
* @param DOMNode $node The node
|
||||
* @param \DOMNode $node The node
|
||||
* @return string
|
||||
*/
|
||||
public static function getSelector( \DOMNode $node )
|
||||
@@ -1269,7 +1265,7 @@ class _plugins extends \IPS\Node\Controller
|
||||
\IPS\Db::i()->delete( 'core_sys_conf_settings', \IPS\Db::i()->in( 'conf_key', $delete ) );
|
||||
}
|
||||
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
\IPS\Settings::i()->clearCache();
|
||||
|
||||
\file_put_contents( $file, json_encode( array_filter( array_values( $values ), function ( $v )
|
||||
{
|
||||
@@ -1567,7 +1563,7 @@ class _plugins extends \IPS\Node\Controller
|
||||
\IPS\Db::i()->insert( 'core_sys_conf_settings', $inserts , TRUE );
|
||||
}
|
||||
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
\IPS\Settings::i()->clearCache();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1844,7 +1840,7 @@ class _plugins extends \IPS\Node\Controller
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C145/B', 404, '' ); //@todo duplicate error code
|
||||
\IPS\Output::i()->error( 'node_error', '2C145/M', 404, '' );
|
||||
}
|
||||
|
||||
/* Work out tab */
|
||||
|
||||
@@ -303,7 +303,7 @@ class _bulkmail extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/* Display */
|
||||
$email = \IPS\Email::buildFromContent( $mail->subject, $content, NULL, \IPS\Email::TYPE_BULK )->setUnsubscribe( 'core', 'unsubscribeBulk' );
|
||||
$email = \IPS\Email::buildFromContent( $mail->subject, \IPS\Email::staticParseTextForEmail( $content, \IPS\Member::loggedIn()->language() ), NULL, \IPS\Email::TYPE_BULK )->setUnsubscribe( 'core', 'unsubscribeBulk' );
|
||||
|
||||
\IPS\Output::i()->sendOutput( $email->compileContent( 'html', \IPS\Member::loggedIn() ) );
|
||||
}
|
||||
@@ -425,7 +425,7 @@ class _bulkmail extends \IPS\Dispatcher\Controller
|
||||
function()
|
||||
{
|
||||
/* We don't have to do anything special because BulkMailer will have already updated the task and disabled the bulk mail */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=bulkmail&controller=bulkmail' ), 'bm_sparkpost_sent' );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=bulkmail&controller=bulkmail' ), 'bm_sent_succesfull' );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -49,6 +49,10 @@ class _clubs extends \IPS\Dispatcher\Controller
|
||||
$table->include = array( 'name', 'type', 'members', 'owner', 'created' );
|
||||
$table->langPrefix = 'club_';
|
||||
$table->parsers = array(
|
||||
'name' => function( $value, $row )
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate('clubs')->name( $value, $row );
|
||||
},
|
||||
'type' => function( $value ) {
|
||||
return \IPS\Theme::i()->getTemplate('clubs')->privacy( $value );
|
||||
},
|
||||
@@ -56,22 +60,26 @@ class _clubs extends \IPS\Dispatcher\Controller
|
||||
return \IPS\DateTime::ts( $value );
|
||||
},
|
||||
'members' => function( $value, $row ) {
|
||||
|
||||
$link = \IPS\Http\Url::internal( "app=core&module=clubs&controller=view&id={$row['id']}&do=members", 'front', 'clubs_view', array( \IPS\Http\Url\Friendly::seoTitle( $row['name'] ) ) );
|
||||
return \IPS\Theme::i()->getTemplate('clubs')->members( $value, $link );
|
||||
if ( $row['type'] !== \IPS\Member\Club::TYPE_PUBLIC )
|
||||
{
|
||||
$link = \IPS\Http\Url::internal( "app=core&module=clubs&controller=view&id={$row['id']}&do=members", 'front', 'clubs_view', array( \IPS\Http\Url\Friendly::seoTitle( $row['name'] ) ) );
|
||||
return \IPS\Theme::i()->getTemplate('clubs')->members( $value, $link );
|
||||
}
|
||||
return '';
|
||||
},
|
||||
'owner' => function( $value ) {
|
||||
return \IPS\Theme::i()->getTemplate('clubs')->owner( \IPS\Member::load( $value ) );
|
||||
},
|
||||
'_highlight' => function( $row ) {
|
||||
if ( !$row['approved'] )
|
||||
{
|
||||
return 'ipsModerated';
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
);
|
||||
$table->noSort = array( 'privacy', 'owner' );
|
||||
$table->sortBy = $table->sortBy ?: 'members';
|
||||
$table->filters = array(
|
||||
'club_type_' . \IPS\Member\Club::TYPE_PUBLIC => array( 'type=?', \IPS\Member\Club::TYPE_PUBLIC ),
|
||||
'club_type_' . \IPS\Member\Club::TYPE_OPEN => array( 'type=?', \IPS\Member\Club::TYPE_OPEN ),
|
||||
'club_type_' . \IPS\Member\Club::TYPE_CLOSED => array( 'type=?', \IPS\Member\Club::TYPE_CLOSED ),
|
||||
'club_type_' . \IPS\Member\Club::TYPE_PRIVATE => array( 'type=?', \IPS\Member\Club::TYPE_PRIVATE )
|
||||
);
|
||||
$table->quickSearch = 'name';
|
||||
$table->advancedSearch = array(
|
||||
'name' => \IPS\Helpers\Table\SEARCH_QUERY_TEXT,
|
||||
@@ -79,14 +87,56 @@ class _clubs extends \IPS\Dispatcher\Controller
|
||||
'owner' => \IPS\Helpers\Table\SEARCH_MEMBER,
|
||||
'created' => \IPS\Helpers\Table\SEARCH_DATE_RANGE,
|
||||
);
|
||||
if ( \IPS\Settings::i()->clubs_require_approval )
|
||||
{
|
||||
$table->filters = array(
|
||||
'pending_approval' => 'approved=0'
|
||||
);
|
||||
$table->advancedSearch['type'] = array( \IPS\Helpers\Table\SEARCH_SELECT, array( 'options' => array(
|
||||
\IPS\Member\Club::TYPE_PUBLIC => 'club_type_' . \IPS\Member\Club::TYPE_PUBLIC,
|
||||
\IPS\Member\Club::TYPE_OPEN => 'club_type_' . \IPS\Member\Club::TYPE_OPEN,
|
||||
\IPS\Member\Club::TYPE_CLOSED => 'club_type_' . \IPS\Member\Club::TYPE_CLOSED,
|
||||
\IPS\Member\Club::TYPE_PRIVATE => 'club_type_' . \IPS\Member\Club::TYPE_PRIVATE,
|
||||
\IPS\Member\Club::TYPE_READONLY => 'club_type_' . \IPS\Member\Club::TYPE_READONLY,
|
||||
), 'multiple' => TRUE ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
$table->filters = array(
|
||||
'club_type_' . \IPS\Member\Club::TYPE_PUBLIC => array( 'type=?', \IPS\Member\Club::TYPE_PUBLIC ),
|
||||
'club_type_' . \IPS\Member\Club::TYPE_OPEN => array( 'type=?', \IPS\Member\Club::TYPE_OPEN ),
|
||||
'club_type_' . \IPS\Member\Club::TYPE_CLOSED => array( 'type=?', \IPS\Member\Club::TYPE_CLOSED ),
|
||||
'club_type_' . \IPS\Member\Club::TYPE_PRIVATE => array( 'type=?', \IPS\Member\Club::TYPE_PRIVATE ),
|
||||
'club_type_' . \IPS\Member\Club::TYPE_READONLY => array( 'type=?', \IPS\Member\Club::TYPE_READONLY )
|
||||
);
|
||||
}
|
||||
$table->rowButtons = function( $row ) {
|
||||
$return = array(
|
||||
'open' => array(
|
||||
'title' => 'view',
|
||||
'icon' => 'search',
|
||||
'link' => \IPS\Http\Url::internal( "app=core&module=clubs&controller=view&id={$row['id']}", 'front', 'clubs_view', array( \IPS\Http\Url\Friendly::seoTitle( $row['name'] ) ) ),
|
||||
'target'=> '_blank'
|
||||
)
|
||||
$return = array();
|
||||
if ( !$row['approved'] )
|
||||
{
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'clubs', 'clubs_edit' ) )
|
||||
{
|
||||
$return['approve'] = array(
|
||||
'title' => 'approve',
|
||||
'icon' => 'check',
|
||||
'link' => \IPS\Http\Url::internal("app=core&module=clubs&controller=clubs&do=approve&id={$row['id']}")
|
||||
);
|
||||
}
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'clubs', 'clubs_delete' ) )
|
||||
{
|
||||
$return['delete'] = array(
|
||||
'title' => 'delete',
|
||||
'icon' => 'times',
|
||||
'link' => \IPS\Http\Url::internal("app=core&module=clubs&controller=clubs&do=delete&id={$row['id']}"),
|
||||
'data' => \IPS\Db::i()->select( 'COUNT(*)', 'core_clubs_node_map', array( 'club_id=?', $row['id'] ) )->first() ? array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('delete') ) : array( 'delete' => '' )
|
||||
);
|
||||
}
|
||||
}
|
||||
$return['open'] = array(
|
||||
'title' => 'view',
|
||||
'icon' => 'search',
|
||||
'link' => \IPS\Http\Url::internal( "app=core&module=clubs&controller=view&id={$row['id']}", 'front', 'clubs_view', array( \IPS\Http\Url\Friendly::seoTitle( $row['name'] ) ) ),
|
||||
'target'=> '_blank'
|
||||
);
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'clubs', 'clubs_edit' ) )
|
||||
{
|
||||
@@ -96,7 +146,7 @@ class _clubs extends \IPS\Dispatcher\Controller
|
||||
'link' => \IPS\Http\Url::internal("app=core&module=clubs&controller=clubs&do=edit&id={$row['id']}")
|
||||
);
|
||||
}
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'clubs', 'clubs_delete' ) )
|
||||
if ( !isset( $return['delete'] ) and \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'clubs', 'clubs_delete' ) )
|
||||
{
|
||||
$return['delete'] = array(
|
||||
'title' => 'delete',
|
||||
@@ -107,25 +157,7 @@ class _clubs extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
return $return;
|
||||
};
|
||||
|
||||
/* Settings Button */
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'clubs', 'fields_manage' ) )
|
||||
{
|
||||
\IPS\Output::i()->sidebar['actions']['settings'] = array(
|
||||
'icon' => 'cog',
|
||||
'title' => 'clubs_custom_fields',
|
||||
'link' => \IPS\Http\Url::internal( "app=core&module=clubs&controller=clubs&controller=fields" ),
|
||||
);
|
||||
}
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'clubs', 'clubs_settings_manage' ) )
|
||||
{
|
||||
\IPS\Output::i()->sidebar['actions']['fields'] = array(
|
||||
'icon' => 'cog',
|
||||
'title' => 'settings',
|
||||
'link' => \IPS\Http\Url::internal( "app=core&module=clubs&controller=clubs&controller=settings" ),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/* Display */
|
||||
\IPS\Output::i()->output = (string) $table;
|
||||
}
|
||||
@@ -244,6 +276,38 @@ class _clubs extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Approve
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function approve()
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'clubs_edit' );
|
||||
|
||||
/* Load Club */
|
||||
try
|
||||
{
|
||||
$club = \IPS\Member\Club::load( \IPS\Request::i()->id );
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C352/8', 404, '' );
|
||||
}
|
||||
|
||||
/* Approve */
|
||||
$club->approved = TRUE;
|
||||
$club->save();
|
||||
|
||||
/* Redirect */
|
||||
$target = \IPS\Http\Url::internal("app=core&module=clubs&controller=clubs");
|
||||
if ( \IPS\Db::i()->select( 'COUNT(*)', 'core_clubs', array( 'approved=0 AND id!=?', $club->id ) )->first() )
|
||||
{
|
||||
$target = $target->setQueryString( 'filter', 'pending_approval' );
|
||||
}
|
||||
\IPS\Output::i()->redirect( $target, "approved" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete
|
||||
*
|
||||
@@ -277,7 +341,7 @@ class _clubs extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
return array_key_exists( 'add', $node->permissionTypes() );
|
||||
}, 'clubs' => TRUE ) );
|
||||
$field->label = $data['name'];
|
||||
$field->label = htmlspecialchars( $data['name'] );
|
||||
$form->add( $field );
|
||||
}
|
||||
catch ( \Exception $e ) {}
|
||||
|
||||
@@ -41,7 +41,25 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
protected function manage()
|
||||
{
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'clubs_enabled_setting', \IPS\Settings::i()->clubs, FALSE, array( 'togglesOn' => array( 'clubs_default_sort', 'clubs_header', 'clubs_locations', 'clubs_modperms', 'clubs_require_approval' ) ) ) );
|
||||
$form->addHeader( 'club_settings' );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'clubs_enabled_setting', \IPS\Settings::i()->clubs, FALSE, array( 'togglesOn' => array( 'clubs_default_sort', 'clubs_header', 'clubs_locations', 'clubs_modperms', 'clubs_require_approval', 'form_header_club_display_settings', 'form_header_club_moderation', 'clubs_default_view', 'clubs_allow_view_change', 'club_nodes_in_apps', 'form_header_clubs_paid_settings', 'clubs_paid_on' ) ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'clubs_require_approval', \IPS\Settings::i()->clubs_require_approval, FALSE, array(), NULL, NULL, NULL, 'clubs_require_approval' ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'clubs_locations', \IPS\Settings::i()->clubs_locations, FALSE, array(), NULL, NULL, NULL, 'clubs_locations' ) );
|
||||
if ( \IPS\Application::appIsEnabled( 'nexus' ) )
|
||||
{
|
||||
$form->addHeader( 'clubs_paid_settings' );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'clubs_paid_on', \IPS\Settings::i()->clubs_paid_on, FALSE, array( 'togglesOn' => array( 'clubs_paid_tax', 'clubs_paid_commission', 'clubs_paid_transfee', 'clubs_paid_gateways' ) ), NULL, NULL, NULL, 'clubs_paid_on' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Node( 'clubs_paid_tax', \IPS\Settings::i()->clubs_paid_tax ?:0, FALSE, array( 'class' => '\IPS\nexus\Tax', 'zeroVal' => 'do_not_tax' ), NULL, NULL, NULL, 'clubs_paid_tax' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'clubs_paid_commission', \IPS\Settings::i()->clubs_paid_commission, FALSE, array( 'min' => 0, 'max' => 100 ), NULL, NULL, '%', 'clubs_paid_commission' ) );
|
||||
$form->add( new \IPS\nexus\Form\Money( 'clubs_paid_transfee', \IPS\Settings::i()->clubs_paid_transfee, FALSE, array(), NULL, NULL, NULL, 'clubs_paid_transfee' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Node( 'clubs_paid_gateways', \IPS\Settings::i()->clubs_paid_gateways, FALSE, array( 'class' => '\IPS\nexus\Gateway', 'zeroVal' => 'no_restriction', 'multiple' => TRUE ), NULL, NULL, NULL, 'clubs_paid_gateways' ) );
|
||||
}
|
||||
$form->addHeader( 'club_display_settings' );
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'clubs_default_view', \IPS\Settings::i()->clubs_default_view, FALSE, array( 'options' => array(
|
||||
'grid' => 'club_view_grid',
|
||||
'list' => 'club_view_list',
|
||||
) ), NULL, NULL, NULL, 'clubs_default_view' ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'clubs_allow_view_change', \IPS\Settings::i()->clubs_allow_view_change, FALSE, array(), NULL, NULL, NULL, 'clubs_allow_view_change' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'clubs_default_sort', \IPS\Settings::i()->clubs_default_sort, FALSE, array( 'options' => array(
|
||||
'last_activity' => 'clubs_sort_last_activity',
|
||||
'members' => 'clubs_sort_members',
|
||||
@@ -53,7 +71,11 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
'full' => 'clubs_header_full',
|
||||
'sidebar' => 'clubs_header_sidebar',
|
||||
) ), NULL, NULL, NULL, 'clubs_header' ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'clubs_locations', \IPS\Settings::i()->clubs_locations, FALSE, array(), NULL, NULL, NULL, 'clubs_locations' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'club_nodes_in_apps', \IPS\Settings::i()->club_nodes_in_apps, FALSE, array( 'options' => array(
|
||||
'0' => 'club_nodes_in_apps_off',
|
||||
'1' => 'club_nodes_in_apps_on',
|
||||
) ), NULL, NULL, NULL, 'club_nodes_in_apps' ) );
|
||||
$form->addHeader( 'club_moderation' );
|
||||
$form->add( new \IPS\Helpers\Form\CheckboxSet( 'clubs_modperms', explode( ',', \IPS\Settings::i()->clubs_modperms ), FALSE, array( 'options' => array(
|
||||
'pin' => 'club_modperm_pin',
|
||||
'unpin' => 'club_modperm_unpin',
|
||||
@@ -70,17 +92,21 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
'delete' => 'club_modperm_delete',
|
||||
'split_merge' => 'club_modperm_split_merge',
|
||||
) ), NULL, NULL, NULL, 'clubs_modperms' ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'clubs_require_approval', \IPS\Settings::i()->clubs_require_approval, FALSE, array(), NULL, NULL, NULL, 'clubs_require_approval' ) );
|
||||
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
{
|
||||
$values['clubs'] = $values['clubs_enabled_setting'];
|
||||
unset( $values['clubs_enabled_setting'] );
|
||||
$values['clubs_modperms'] = implode( ',', $values['clubs_modperms'] );
|
||||
$values['clubs_modperms'] = implode( ',', $values['clubs_modperms'] );
|
||||
if ( \IPS\Application::appIsEnabled( 'nexus' ) )
|
||||
{
|
||||
$values['clubs_paid_tax'] = $values['clubs_paid_tax'] ? $values['clubs_paid_tax']->id : 0;
|
||||
$values['clubs_paid_gateways'] = is_array( $values['clubs_paid_gateways'] ) ? implode( ',', array_keys( $values['clubs_paid_gateways'] ) ) : $values['clubs_paid_gateways'];
|
||||
}
|
||||
$form->saveAsSettings( $values );
|
||||
|
||||
\IPS\Session::i()->log( 'acplog__club_settings' );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=core&module=clubs&controller=clubs') );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=core&module=clubs&controller=settings') );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__core_clubs_settings');
|
||||
|
||||
@@ -135,14 +135,14 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$templateBits = $skinSet->getRawTemplates( $t_app, $t_location, $t_group, \IPS\Theme::RETURN_ALL );
|
||||
$templateBit = ( ! empty( $t_name ) ) ? $templateBits[ $t_app ][ $t_location ][ $t_group ][ $t_name ] : null;
|
||||
$templateBit['template_content'] = htmlentities( $templateBit['template_content'], \IPS\HTMLENTITIES, 'UTF-8', TRUE );
|
||||
$templateBit['template_content'] = htmlentities( $templateBit['template_content'], ENT_DISALLOWED, 'UTF-8', TRUE );
|
||||
}
|
||||
else
|
||||
{
|
||||
$templateNames = $skinSet->getRawCss( '', '', '', \IPS\Theme::RETURN_ALL_NO_CONTENT );
|
||||
$templateBits = $skinSet->getRawCss( $t_app, $t_location, $t_group, \IPS\Theme::RETURN_ALL );
|
||||
$templateBit = ( ! empty( $t_name ) ) ? $templateBits[ $t_app ][ $t_location ][ $t_group ][ $t_name ] : null;
|
||||
$templateBit['css_content'] = htmlentities( $templateBit['css_content'], \IPS\HTMLENTITIES, 'UTF-8', TRUE );
|
||||
$templateBit['css_content'] = htmlentities( $templateBit['css_content'], ENT_DISALLOWED, 'UTF-8', TRUE );
|
||||
}
|
||||
|
||||
if ( $templateBit !== null )
|
||||
@@ -182,12 +182,12 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
foreach ( $templates as $template )
|
||||
{
|
||||
$uniqueIds[] = "'" . $template['template_unique_key'] . "'";
|
||||
$uniqueIds[] = md5( $template['template_app'] . ',' . $template['template_location'] . ',' . $template['template_group'] . ',' . $template['template_name'] );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$where[] = array( 'template_unique_key IN (' . implode( ',' , $uniqueIds ) . ')' );
|
||||
$where[] = array( \IPS\Db::i()->in( "MD5( CONCAT_WS( ',', template_app, template_location, template_group, template_name ) )", $uniqueIds ) );
|
||||
}
|
||||
if ( in_array( 'inherited', explode( ',', \IPS\Request::i()->filters ) ) )
|
||||
{
|
||||
@@ -221,7 +221,7 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
$where,
|
||||
'template_location, template_group, template_name, theorder desc'
|
||||
);
|
||||
|
||||
|
||||
$return = array();
|
||||
foreach( $select as $result )
|
||||
{
|
||||
@@ -269,12 +269,12 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
foreach ( $templates as $template )
|
||||
{
|
||||
$uniqueIds[] = "'" . $template['css_unique_key'] . "'";
|
||||
$uniqueIds[] = md5( $template['css_set_id'] . ',' . $template['css_app'] . ',' . $template['css_location'] . ',' . $template['css_path'] . ',' . $template['css_name'] );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$where[] = array( 'css_unique_key IN (' . implode( ',' , $uniqueIds ) . ')' );
|
||||
$where[] = array( \IPS\Db::i()->in( "MD5( CONCAT_WS( ',', css_set_id, css_app, css_location, css_path, css_name ) )", $uniqueIds ) );
|
||||
}
|
||||
if ( in_array( 'inherited', explode( ',', \IPS\Request::i()->filters ) ) )
|
||||
{
|
||||
|
||||
@@ -48,8 +48,13 @@ class _emails extends \IPS\Dispatcher\Controller
|
||||
$table->quickSearch = 'template_name';
|
||||
$table->limit = 100;
|
||||
|
||||
/* Primary Sort */
|
||||
$table->primarySortBy = 'template_pinned';
|
||||
$table->primarySortDirection = 'desc';
|
||||
|
||||
/* Default sort options */
|
||||
$table->noSort = array( 'template_name' );
|
||||
$table->sortBy = $table->sortBy ?: 'template_id';
|
||||
$table->sortDirection = $table->sortDirection ?: 'desc';
|
||||
|
||||
$table->quickSearch = function( $val )
|
||||
@@ -61,7 +66,7 @@ class _emails extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
else
|
||||
{
|
||||
return "`template_name` LIKE '%{$val}%'";
|
||||
return "`template_name` LIKE '%" . \IPS\Db::i()->escape_string( $val ) . "%'";
|
||||
}
|
||||
};
|
||||
|
||||
@@ -175,11 +180,18 @@ class _emails extends \IPS\Dispatcher\Controller
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
/* Open XML file */
|
||||
$xml = \IPS\Xml\SimpleXML::loadFile( $values['email_template_file'] );
|
||||
|
||||
if( !count($xml->template) )
|
||||
try
|
||||
{
|
||||
\IPS\Output::i()->error( 'email_template_badform', '1S128/4', 403, '' );
|
||||
$xml = \IPS\Xml\SimpleXML::loadFile( $values['email_template_file'] );
|
||||
|
||||
if( !count($xml->template) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'email_template_badform', '1S128/4', 403, '' );
|
||||
}
|
||||
}
|
||||
catch( \InvalidArgumentException $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'email_template_badform', '1C373/1', 403, '' );
|
||||
}
|
||||
|
||||
foreach( $xml->template as $template )
|
||||
|
||||
@@ -205,8 +205,7 @@ class _themes extends \IPS\Node\Controller
|
||||
else
|
||||
{
|
||||
/* Toggle the setting */
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => 0 ), array( 'conf_key=?', 'theme_designers_mode' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
\IPS\Settings::i()->changeValues( array( 'theme_designers_mode' => 0 ) );
|
||||
|
||||
/* Finished */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=customization&controller=themes&do=manage' ), 'saved' );
|
||||
@@ -376,7 +375,7 @@ class _themes extends \IPS\Node\Controller
|
||||
|
||||
$_SESSION['theme_dev_import'] = $toImport;
|
||||
|
||||
return array( $data, \IPS\Member::loggedIn()->language()->addToStack('theme_dev_import', FALSE, array( 'sprintf' => array( $theme->_title, ucfirst( $app ) ) ) ) );
|
||||
return array( $data, \IPS\Member::loggedIn()->language()->addToStack('theme_dev_import', FALSE, array( 'sprintf' => array( $theme->_title, mb_ucfirst( $app ) ) ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -412,8 +411,7 @@ class _themes extends \IPS\Node\Controller
|
||||
unset( $_SESSION['theme_dev_import'] );
|
||||
|
||||
/* Toggle the setting */
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => 0 ), array( 'conf_key=?', 'theme_designers_mode' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
\IPS\Settings::i()->changeValues( array( 'theme_designers_mode' => 0 ) );
|
||||
|
||||
/* Finished */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=customization&controller=themes&do=manage' ), 'completed' );
|
||||
@@ -457,8 +455,7 @@ class _themes extends \IPS\Node\Controller
|
||||
if ( ! $needsBuilding )
|
||||
{
|
||||
/* Toggle the setting */
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => 1 ), array( 'conf_key=?', 'theme_designers_mode' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
\IPS\Settings::i()->changeValues( array( 'theme_designers_mode' => 1 ) );
|
||||
|
||||
/* Finished */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=customization&controller=themes&do=manage' ), 'completed' );
|
||||
@@ -591,8 +588,7 @@ class _themes extends \IPS\Node\Controller
|
||||
function()
|
||||
{
|
||||
/* Toggle the setting */
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => 1 ), array( 'conf_key=?', 'theme_designers_mode' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
\IPS\Settings::i()->changeValues( array( 'theme_designers_mode' => 1 ) );
|
||||
|
||||
/* Finished */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=customization&controller=themes&do=manage' ), 'completed' );
|
||||
@@ -828,7 +824,7 @@ class _themes extends \IPS\Node\Controller
|
||||
\IPS\Member::loggedIn()->language()->words['core_theme_resource_name_choice_o_filename_desc'] = sprintf( \IPS\Member::loggedIn()->language()->get('core_theme_resource_name_choice_o_filename_desc'), $current['resource_name'] );
|
||||
}
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Upload( 'core_theme_resource_filename', ( isset( $current['resource_filename'] ) ? \IPS\File::get( 'core_Theme', $current['resource_filename'] ) : NULL ), FALSE, array( 'obscure' => FALSE, 'maxFileSize' => 1.2, 'storageExtension' => 'core_Theme', 'storageContainer' => 'set_resources_' . $set->_id ), NULL, NULL, NULL, 'core_theme_resource_filename' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Upload( 'core_theme_resource_filename', ( isset( $current['resource_filename'] ) ? \IPS\File::get( 'core_Theme', $current['resource_filename'] ) : NULL ), TRUE, array( 'obscure' => FALSE, 'maxFileSize' => 1.2, 'storageExtension' => 'core_Theme', 'storageContainer' => 'set_resources_' . $set->_id ), NULL, NULL, NULL, 'core_theme_resource_filename' ) );
|
||||
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
@@ -865,7 +861,7 @@ class _themes extends \IPS\Node\Controller
|
||||
\IPS\Db::i()->select( '*', 'core_theme_resources', array( 'resource_set_id=? and resource_path=? and resource_location=? and resource_app=? and resource_name=?', $set->_id, $save['resource_path'], $save['resource_location'], $save['resource_app'], $save['resource_name'] ) )->first();
|
||||
|
||||
$ext = mb_substr( $save['resource_name'], ( mb_strrpos( $save['resource_name'], '.' ) + 1 ) );
|
||||
$save['resource_name'] = mb_substr( $save['resource_name'], 0, ( mb_strrpos( $save['resource_name'], '.' ) ) ) . '_' . uniqid() . '.' . $ext;
|
||||
$save['resource_name'] = mb_substr( $save['resource_name'], 0, ( mb_strrpos( $save['resource_name'], '.' ) ) ) . '_' . mt_rand() . '.' . $ext;
|
||||
}
|
||||
catch( \UnderflowException $ex ) { }
|
||||
|
||||
@@ -894,6 +890,8 @@ class _themes extends \IPS\Node\Controller
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=customization&controller=themes&do=resources&set_id=' . $set->_id ), 'saved' );
|
||||
}
|
||||
|
||||
\IPS\Theme::setThemeCustomized( $set->_id );
|
||||
|
||||
/* Display */
|
||||
$title = \IPS\Member::loggedIn()->language()->addToStack('theme_custom_resources_page_title', FALSE, array( 'sprintf' => array( $set->_title ) ) );
|
||||
@@ -1053,7 +1051,7 @@ class _themes extends \IPS\Node\Controller
|
||||
{
|
||||
$_SESSION['theme_import'] = array( 'css' => array(), 'isNewSet' => false );
|
||||
|
||||
/* Save snaphot */
|
||||
/* Save snapshot */
|
||||
\IPS\Theme::load( \IPS\Request::i()->id )->saveHistorySnapshot();
|
||||
|
||||
/* Wipe clean conflicts */
|
||||
@@ -1122,7 +1120,7 @@ class _themes extends \IPS\Node\Controller
|
||||
}
|
||||
}
|
||||
|
||||
/* Start impoprting */
|
||||
/* Start importing */
|
||||
$data = array( 'apps' => array() );
|
||||
return array( $data, \IPS\Member::loggedIn()->language()->addToStack('processing') );
|
||||
}
|
||||
@@ -1220,6 +1218,7 @@ class _themes extends \IPS\Node\Controller
|
||||
$location = $xml->getAttribute('template_location');
|
||||
$group = $xml->getAttribute('template_group');
|
||||
$name = $xml->getAttribute('template_name');
|
||||
$isMaster = \IPS\Db::i()->select( 'COUNT(*)', 'core_theme_templates', array( 'template_app=? and template_location=? and template_group=? and template_name=? and template_set_id=0 and template_added_to=0', $appKey, $location, $group, $name ) )->first();
|
||||
|
||||
if ( isset( $templates[ $appKey ][ $location ][ $group ][ $name ] ) AND $templates[ $appKey ][ $location ][ $group ][ $name ]['template_user_edited'] )
|
||||
{
|
||||
@@ -1249,11 +1248,10 @@ class _themes extends \IPS\Node\Controller
|
||||
'template_content' => $xml->readString(),
|
||||
'template_updated' => time(),
|
||||
'template_removable' => 1,
|
||||
'template_user_added' => 0,
|
||||
'template_user_added' => $isMaster ? 0 : 1,
|
||||
'template_user_edited'=> 0,
|
||||
'template_version' => $version,
|
||||
'template_added_to' => \IPS\Request::i()->id,
|
||||
'template_unique_key' => md5( \IPS\Request::i()->id . ';' . $appKey . ';' . $location . ';' . $group . ';' . mb_strtolower( $name ) )
|
||||
'template_added_to' => \IPS\Request::i()->id
|
||||
) );
|
||||
}
|
||||
break;
|
||||
@@ -1262,6 +1260,9 @@ class _themes extends \IPS\Node\Controller
|
||||
$path = $xml->getAttribute('css_path');
|
||||
$name = $xml->getAttribute('css_name');
|
||||
|
||||
$isMaster = \IPS\Db::i()->select( 'COUNT(*)', 'core_theme_css', array( 'css_app=? and css_location=? and css_path=? and css_name=? and css_set_id=0 and css_added_to=0', $appKey, $location, $path, $name ) )->first();
|
||||
|
||||
|
||||
if ( isset( $css[ $appKey ][ $location ][ $path ][ $name ] ) AND $css[ $appKey ][ $location ][ $path ][ $name ]['css_user_edited'] )
|
||||
{
|
||||
/* Keep this */
|
||||
@@ -1286,7 +1287,7 @@ class _themes extends \IPS\Node\Controller
|
||||
$edited = 0;
|
||||
$addedTo = \IPS\Request::i()->id;
|
||||
|
||||
if ( in_array( $name, $masterCss[ $appKey ][ $location ][ $path ] ) )
|
||||
if ( $isMaster )
|
||||
{
|
||||
$edited = time();
|
||||
$addedTo = 0;
|
||||
@@ -1303,8 +1304,7 @@ class _themes extends \IPS\Node\Controller
|
||||
'css_content' => $xml->readString(),
|
||||
'css_version' => $version,
|
||||
'css_user_edited'=> $edited,
|
||||
'css_added_to' => $addedTo,
|
||||
'css_unique_key' => md5( \IPS\Request::i()->id . ';' . $xml->getAttribute('css_app') . ';' . $xml->getAttribute('css_location') . ';' . $xml->getAttribute('css_path') . ';' . $xml->getAttribute('css_name') )
|
||||
'css_added_to' => $addedTo
|
||||
), true );
|
||||
}
|
||||
break;
|
||||
@@ -1464,6 +1464,8 @@ class _themes extends \IPS\Node\Controller
|
||||
$app->installThemeSettings( true );
|
||||
}
|
||||
|
||||
\IPS\Theme::setThemeCustomized( $set->id );
|
||||
|
||||
/* Conflicts to fix? */
|
||||
if ( \IPS\Db::i()->select( 'count(*)', 'core_theme_conflict', array( 'conflict_set_id=?', \IPS\Request::i()->id ) )->first() )
|
||||
{
|
||||
@@ -1979,7 +1981,7 @@ class _themes extends \IPS\Node\Controller
|
||||
|
||||
/* Templates */
|
||||
$templates = $themeSet->getRawTemplates( $appDir, '', '', \IPS\Theme::RETURN_ALL );
|
||||
if ( count( $templates[ $appDir->directory ] ) )
|
||||
if ( isset( $templates[ $appDir->directory ] ) AND count( $templates[ $appDir->directory ] ) )
|
||||
{
|
||||
foreach( $templates[ $appDir->directory ] as $loc => $lv )
|
||||
{
|
||||
@@ -2360,7 +2362,8 @@ class _themes extends \IPS\Node\Controller
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$id = intval( \IPS\Request::i()->id );
|
||||
$save = array( 'app' => $values['theme_template_app'],
|
||||
$save = array( 'set_id' => $id,
|
||||
'app' => $values['theme_template_app'],
|
||||
'location' => $values['theme_template_location'],
|
||||
'group' => ( $values['theme_template_group_type'] == 'existing' ) ? $values['theme_template_group_existing'] : $values['theme_template_group_new'],
|
||||
'name' => $values['theme_template_name'],
|
||||
@@ -2468,6 +2471,11 @@ class _themes extends \IPS\Node\Controller
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '3S121/1', 500, '' );
|
||||
}
|
||||
catch( \UnderflowException $ex )
|
||||
{
|
||||
/* This means the template to delete was not found - so we really don't need to worry about the error */
|
||||
$template = array();
|
||||
}
|
||||
|
||||
if ( isset( $template['app'] ) )
|
||||
{
|
||||
@@ -2531,8 +2539,14 @@ class _themes extends \IPS\Node\Controller
|
||||
}
|
||||
catch( \OutOfRangeException $ex )
|
||||
{
|
||||
\IPS\Log::log( $ex, 'template_error' );
|
||||
\IPS\Output::i()->error( 'node_error', '3S121/2', 500, '' );
|
||||
}
|
||||
catch( \UnderflowException $ex )
|
||||
{
|
||||
\IPS\Log::log( $ex, 'template_error' );
|
||||
\IPS\Output::i()->error( 'node_error', '3C163/I', 500, '' );
|
||||
}
|
||||
catch( \InvalidArgumentException $ex )
|
||||
{
|
||||
$msg = $ex->getMessage();
|
||||
@@ -2758,7 +2772,7 @@ class _themes extends \IPS\Node\Controller
|
||||
{
|
||||
$customVersion = \IPS\Db::i()->select( '*', 'core_theme_templates', array( 'template_id=?', (int) \IPS\Request::i()->t_item_id ) )->first();
|
||||
$rawTemplates = \IPS\Theme::master()->getRawTemplates( $customVersion['template_app'], $customVersion['template_location'], $customVersion['template_group'], \IPS\Theme::RETURN_ALL, TRUE );
|
||||
$original = $rawTemplates[ $customVersion['template_app'] ][ $customVersion['template_location'] ][ $customVersion['template_group'] ][ $customVersion['template_name'] ]['template_content'];
|
||||
$original = isset( $rawTemplates[ $customVersion['template_app'] ][ $customVersion['template_location'] ][ $customVersion['template_group'] ][ $customVersion['template_name'] ] ) ? $rawTemplates[ $customVersion['template_app'] ][ $customVersion['template_location'] ][ $customVersion['template_group'] ][ $customVersion['template_name'] ]['template_content'] : '';
|
||||
}
|
||||
|
||||
\IPS\Output::i()->json( $original );
|
||||
|
||||
@@ -413,7 +413,7 @@ class _themesettings extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'theme_custom_setting_conditional', $id ? $current['sc_condition'] : FALSE, FALSE, array( 'togglesOn' => array( 'theme_custom_setting_condition' ) ), NULL, NULL, NULL, 'theme_custom_setting_conditional' ) );
|
||||
$form->add( new \IPS\Helpers\Form\CodeMirror( 'theme_custom_setting_condition', '<?php' . "\n\n" . ( ( $id and $current['sc_condition'] ) ? $current['sc_condition'] : 'return TRUE;' ), FALSE, array( 'mode' => 'php' ), NULL, NULL, NULL, 'theme_custom_setting_condition' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Codemirror( 'theme_custom_setting_condition', '<?php' . "\n\n" . ( ( $id and $current['sc_condition'] ) ? $current['sc_condition'] : 'return TRUE;' ), FALSE, array( 'mode' => 'php' ), NULL, NULL, NULL, 'theme_custom_setting_condition' ) );
|
||||
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
|
||||
@@ -51,18 +51,140 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
);
|
||||
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'search_index_timeframe', \IPS\Settings::i()->search_index_timeframe, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'all' ), NULL, \IPS\Member::loggedIn()->language()->addToStack('search_index_timeframe_prefix'), \IPS\Member::loggedIn()->language()->addToStack('search_index_timeframe_suffix'), 'search_index_timeframe' ) );
|
||||
|
||||
$form->addHeader('search_method');
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'search_method', \IPS\Settings::i()->search_method, FALSE, array(
|
||||
'options' => array(
|
||||
'mysql' => 'search_method_mysql',
|
||||
'elastic' => 'search_method_elastic'
|
||||
),
|
||||
'toggles' => array(
|
||||
'mysql' => array( 'search_index_timeframe' ),
|
||||
'elastic' => array( 'search_elastic_server', 'search_elastic_index', 'search_elastic_analyzer', 'search_decay', 'search_elastic_self_boost' )
|
||||
)
|
||||
) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Url( 'search_elastic_server', \IPS\Settings::i()->search_elastic_server, NULL, array( 'placeholder' => 'http://localhost:9200' ), function( $val )
|
||||
{
|
||||
if( \IPS\Request::i()->search_method != 'elastic' )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if( !( $val instanceof \IPS\Http\Url ) )
|
||||
{
|
||||
throw new \DomainException('form_url_error');
|
||||
}
|
||||
|
||||
$requiredVersion = '5.5.0';
|
||||
try
|
||||
{
|
||||
$response = $val->request()->get()->decodeJson();
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
throw new \DomainException( \IPS\Member::loggedIn()->language()->addToStack('search_elastic_server_error', FALSE, array( 'sprintf' => array( $e->getMessage() ) ) ) );
|
||||
}
|
||||
if ( !isset( $response['version']['number'] ) )
|
||||
{
|
||||
throw new \DomainException('search_elastic_server_no_version');
|
||||
}
|
||||
if ( version_compare( $response['version']['number'], $requiredVersion, '<' ) )
|
||||
{
|
||||
throw new \DomainException( \IPS\Member::loggedIn()->language()->addToStack('search_elastic_server_unsupported_version', FALSE, array( 'sprintf' => array( $requiredVersion, $response['version']['number'] ) ) ) );
|
||||
}
|
||||
}, NULL, NULL, 'search_elastic_server' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'search_elastic_index', \IPS\Settings::i()->search_elastic_index, NULL, array( 'regex' => '/^[A-Z0-9_]*$/i' ), NULL, NULL, NULL, 'search_elastic_index' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Select( 'search_elastic_analyzer', \IPS\Settings::i()->search_elastic_analyzer, FALSE, array( 'options' => array(
|
||||
'standard' => 'elastic_analyzer_standard',
|
||||
'arabic' => 'elastic_analyzer_arabic',
|
||||
'armenian' => 'elastic_analyzer_armenian',
|
||||
'basque' => 'elastic_analyzer_basque',
|
||||
'brazilian' => 'elastic_analyzer_brazilian',
|
||||
'bulgarian' => 'elastic_analyzer_bulgarian',
|
||||
'catalan' => 'elastic_analyzer_catalan',
|
||||
'cjk' => 'elastic_analyzer_cjk',
|
||||
'czech' => 'elastic_analyzer_czech',
|
||||
'danish' => 'elastic_analyzer_danish',
|
||||
'dutch' => 'elastic_analyzer_dutch',
|
||||
'english' => 'elastic_analyzer_english',
|
||||
'finnish' => 'elastic_analyzer_finnish',
|
||||
'french' => 'elastic_analyzer_french',
|
||||
'galician' => 'elastic_analyzer_galician',
|
||||
'german' => 'elastic_analyzer_german',
|
||||
'greek' => 'elastic_analyzer_greek',
|
||||
'hindi' => 'elastic_analyzer_hindi',
|
||||
'hungarian' => 'elastic_analyzer_hungarian',
|
||||
'indonesian' => 'elastic_analyzer_indonesian',
|
||||
'irish' => 'elastic_analyzer_irish',
|
||||
'italian' => 'elastic_analyzer_italian',
|
||||
'latvian' => 'elastic_analyzer_latvian',
|
||||
'lithuanian' => 'elastic_analyzer_lithuanian',
|
||||
'norwegian' => 'elastic_analyzer_norwegian',
|
||||
'persian' => 'elastic_analyzer_persian',
|
||||
'portuguese' => 'elastic_analyzer_portuguese',
|
||||
'romanian' => 'elastic_analyzer_romanian',
|
||||
'russian' => 'elastic_analyzer_russian',
|
||||
'sorani' => 'elastic_analyzer_sorani',
|
||||
'spanish' => 'elastic_analyzer_spanish',
|
||||
'swedish' => 'elastic_analyzer_swedish',
|
||||
'turkish' => 'elastic_analyzer_turkish',
|
||||
'thai' => 'elastic_analyzer_thai',
|
||||
) ), NULL, NULL, NULL, 'search_elastic_analyzer' ) );
|
||||
$form->addHeader('search_options');
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'search_default_operator', \IPS\Settings::i()->search_default_operator, FALSE, array( 'options' => array(
|
||||
'or' => 'search_default_operator_or',
|
||||
'and' => 'search_default_operator_and',
|
||||
) ), NULL, \IPS\Member::loggedIn()->language()->addToStack('search_default_operator_prefix') ) );
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'search_title_boost', \IPS\Settings::i()->search_title_boost, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'search_title_boost_unlimited' ), NULL, \IPS\Member::loggedIn()->language()->addToStack('search_title_boost_prefix'), \IPS\Member::loggedIn()->language()->addToStack('search_title_boost_suffix'), 'search_title_boost' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Custom( 'search_decay', array( \IPS\Settings::i()->search_decay_days, \IPS\Settings::i()->search_decay_factor ), FALSE, array(
|
||||
'getHtml' => function( $field ) {
|
||||
return \IPS\Theme::i()->getTemplate( 'settings' )->searchDecay( isset( $field->value[0] ) ? $field->value[0] : 0, isset( $field->value[1] ) ? $field->value[1] : 0 );
|
||||
}
|
||||
), NULL, NULL, NULL, 'search_decay' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'search_elastic_self_boost', \IPS\Settings::i()->search_elastic_self_boost, FALSE, array( 'unlimited' => floatval( 0 ), 'unlimitedLang' => 'do_not_boost', 'decimals' => 1 ), NULL, \IPS\Member::loggedIn()->language()->addToStack('search_elastic_self_boost_prefix'), \IPS\Member::loggedIn()->language()->addToStack('search_elastic_self_boost_suffix'), 'search_elastic_self_boost' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'search_index_timeframe', \IPS\Settings::i()->search_index_timeframe, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'search_index_timeframe_unlimited' ), NULL, \IPS\Member::loggedIn()->language()->addToStack('search_index_timeframe_prefix'), \IPS\Member::loggedIn()->language()->addToStack('search_index_timeframe_suffix'), 'search_index_timeframe' ) );
|
||||
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$engine = \IPS\Settings::i()->search_method;
|
||||
$indexPrune = \IPS\Settings::i()->search_index_timeframe;
|
||||
$analyzer = \IPS\Settings::i()->search_elastic_analyzer;
|
||||
|
||||
if ( isset( $values['search_decay'][2] ) )
|
||||
{
|
||||
$values['search_decay_days'] = 0;
|
||||
$values['search_decay_factor'] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
$values['search_decay_days'] = $values['search_decay'][0];
|
||||
$values['search_decay_factor'] = $values['search_decay'][1];
|
||||
}
|
||||
unset( $values['search_decay'] );
|
||||
|
||||
if( $engine != $values['search_method'] )
|
||||
{
|
||||
try
|
||||
{
|
||||
\IPS\Content\Search\Index::i()->prune();
|
||||
}
|
||||
catch( \Exception $e )
|
||||
{
|
||||
\IPS\Log::log( $e, 'search_index_prune' );
|
||||
}
|
||||
}
|
||||
|
||||
/* Go ahead and save... */
|
||||
$form->saveAsSettings();
|
||||
$form->saveAsSettings( $values );
|
||||
\IPS\Session::i()->log( 'acplogs__search_settings' );
|
||||
|
||||
/* And re-index if setting updated */
|
||||
if( $indexPrune != $values['search_index_timeframe'] )
|
||||
if( $engine != $values['search_method'] or ( $values['search_method'] == 'elastic' and $values['search_elastic_analyzer'] != $analyzer ) )
|
||||
{
|
||||
/* We pass TRUE to the i() method to ensure we get a new instance, otherwise the old instance cached from the previous prune call will be used */
|
||||
\IPS\Content\Search\Index::i( TRUE )->init();
|
||||
\IPS\Content\Search\Index::i()->rebuild();
|
||||
}
|
||||
elseif( $indexPrune != $values['search_index_timeframe'] )
|
||||
{
|
||||
\IPS\Content\Search\Index::i()->rebuild();
|
||||
}
|
||||
|
||||
@@ -41,24 +41,62 @@ class _emoticons extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function manage()
|
||||
{
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__core_editor_emoticons');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'customization' )->emoticons( $this->_getEmoticons() );
|
||||
$tabs = array(
|
||||
'standard' => 'standard_emoji',
|
||||
'custom' => 'custom_emoji',
|
||||
);
|
||||
$activeTab = ( isset( \IPS\Request::i()->tab ) and array_key_exists( \IPS\Request::i()->tab, $tabs ) ) ? \IPS\Request::i()->tab : 'standard';
|
||||
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'editor', 'emoticons_edit' ) )
|
||||
if ( $activeTab == 'standard' )
|
||||
{
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js('admin_customization.js', 'core', 'admin') );
|
||||
if ( \IPS\Settings::i()->getFromConfGlobal('sql_utf8mb4') )
|
||||
{
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'emoji_style', \IPS\Settings::i()->emoji_style, FALSE, array(
|
||||
'options' => array(
|
||||
'native' => 'emoji_style_native',
|
||||
'twemoji' => 'emoji_style_twemoji',
|
||||
'emojione' => 'emoji_style_emojione',
|
||||
'disabled' => 'emoji_style_disabled',
|
||||
),
|
||||
'toggles' => array(
|
||||
'native' => array( 'emoji_shortcodes', 'emoji_ascii' ),
|
||||
'twemoji' => array( 'emoji_shortcodes', 'emoji_ascii' ),
|
||||
'emojione' => array( 'emoji_shortcodes', 'emoji_ascii' ),
|
||||
),
|
||||
) ) );
|
||||
\IPS\Member::loggedIn()->language()->get( 'emoji_style_native' ); // We need to preload the word before we can add more text to it.
|
||||
\IPS\Member::loggedIn()->language()->words['emoji_style_native'] .= "<br><div class='ipsType_large ipsSpacer_top ipsSpacer_half'><span class='ipsEmoji'>😀</span><span class='ipsEmoji'>😉</span><span class='ipsEmoji'>😂</span><span class='ipsEmoji'>😍</span><span class='ipsEmoji'>🤘</span><span class='ipsEmoji'>🤦♀️</span><span class='ipsEmoji'>🤷♂️</span><span class='ipsEmoji'>🍿</span><span class='ipsEmoji'>🚀</span><span class='ipsEmoji'>🎉</span><span class='ipsEmoji'>🏳️🌈</span></div>"; // Have to do this here because if we try to put it in the actual language string, that will cause an error if not utf8mb4
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'emoji_shortcodes', \IPS\Settings::i()->emoji_shortcodes, FALSE, array(), NULL, NULL, NULL, 'emoji_shortcodes' ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'emoji_ascii', \IPS\Settings::i()->emoji_ascii, FALSE, array(), NULL, NULL, NULL, 'emoji_ascii' ) );
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$values['emoji_cache'] = time();
|
||||
$form->saveAsSettings( $values );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=editor&controller=emoticons&tab=standard' ), 'saved' );
|
||||
}
|
||||
|
||||
$activeTabContents = $form;
|
||||
}
|
||||
else
|
||||
{
|
||||
$activeTabContents = \IPS\Theme::i()->getTemplate( 'global' )->message( 'emoji_utf8mb4_required', 'error', NULL, TRUE, TRUE );
|
||||
}
|
||||
}
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'editor', 'emoticons_add' ) )
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->sidebar['actions'] = array(
|
||||
'add' => array(
|
||||
'primary' => TRUE,
|
||||
'icon' => 'plus-circle',
|
||||
'title' => 'emoticons_add',
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=editor&controller=emoticons&do=add' ),
|
||||
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('emoticons_add') )
|
||||
),
|
||||
);
|
||||
$activeTabContents = \IPS\Theme::i()->getTemplate( 'customization' )->emoticons( $this->_getEmoticons() );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__core_editor_emoticons');
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js('admin_customization.js', 'core', 'admin') );
|
||||
if( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->output = $activeTabContents;
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global' )->tabs( $tabs, $activeTab, $activeTabContents, \IPS\Http\Url::internal( "app=core&module=editor&controller=emoticons" ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +145,7 @@ class _emoticons extends \IPS\Dispatcher\Controller
|
||||
if ( $values['emoticons_add_group'] === 'create' )
|
||||
{
|
||||
$position = 0;
|
||||
$setId = md5( uniqid() );
|
||||
$setId = mt_rand();
|
||||
\IPS\Lang::saveCustom( 'core', "core_emoticon_group_{$setId}", $values['emoticons_add_newgroup'] );
|
||||
\IPS\Session::i()->log( 'acplog__emoticon_group_created', array( "core_emoticon_group_{$setId}" => TRUE ) );
|
||||
}
|
||||
@@ -185,14 +223,15 @@ class _emoticons extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
unset( \IPS\Data\Store::i()->emoticons );
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => time() ), array( 'conf_key=?', 'emoji_cache' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
|
||||
/* Clear guest page caches */
|
||||
\IPS\Data\Cache::i()->clearAll();
|
||||
|
||||
\IPS\Session::i()->log( 'acplog__emoticons_added', array( "core_emoticon_group_{$setId}" => TRUE ) );
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=editor&controller=emoticons' ), 'saved' );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=editor&controller=emoticons&tab=custom' ), 'saved' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global' )->block( 'emoticons_add', $form, FALSE );
|
||||
@@ -242,11 +281,32 @@ class _emoticons extends \IPS\Dispatcher\Controller
|
||||
$setPos++;
|
||||
}
|
||||
}
|
||||
unset( \IPS\Data\Store::i()->emoticons );
|
||||
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => time() ), array( 'conf_key=?', 'emoji_cache' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
|
||||
\IPS\Output::i()->json( 'OK' );
|
||||
return;
|
||||
}
|
||||
|
||||
// Do we need to unsquash any values?
|
||||
// Squashed values are json_encoded by javascript to prevent us exceeding max_post_vars
|
||||
// If 'squashedField' isn't in the request it might indicate the user didn't have JS enabled
|
||||
if ( isset( \IPS\Request::i()->emoticons_squashed ) )
|
||||
{
|
||||
if ( isset( \IPS\Request::i()->emoticons_squashed ) )
|
||||
{
|
||||
$unsquashed = json_decode( \IPS\Request::i()->emoticons_squashed, TRUE );
|
||||
|
||||
foreach( $unsquashed as $key => $value )
|
||||
{
|
||||
\IPS\Request::i()->$key = $value;
|
||||
}
|
||||
|
||||
unset( \IPS\Request::i()->emoticons_squashed );
|
||||
}
|
||||
}
|
||||
|
||||
$emoticons = $this->_getEmoticons( FALSE );
|
||||
|
||||
foreach ( \IPS\Request::i()->emo as $id => $data )
|
||||
@@ -284,14 +344,15 @@ class _emoticons extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
unset( \IPS\Data\Store::i()->emoticons );
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => time() ), array( 'conf_key=?', 'emoji_cache' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
|
||||
/* Clear guest page caches */
|
||||
\IPS\Data\Cache::i()->clearAll();
|
||||
|
||||
\IPS\Session::i()->log( 'acplog__emoticons_edited' );
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=editor&controller=emoticons' ), 'saved' );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=editor&controller=emoticons&tab=custom' ), 'saved' );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -327,14 +388,15 @@ class _emoticons extends \IPS\Dispatcher\Controller
|
||||
|
||||
\IPS\Session::i()->log( 'acplog__emoticon_deleted' );
|
||||
|
||||
unset( \IPS\Data\Store::i()->emoticons );
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => time() ), array( 'conf_key=?', 'emoji_cache' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
|
||||
/* Clear guest page caches */
|
||||
\IPS\Data\Cache::i()->clearAll();
|
||||
}
|
||||
catch ( \UnderflowException $e ) { }
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=editor&controller=emoticons' ), 'saved' );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=editor&controller=emoticons&tab=custom' ), 'saved' );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -364,12 +426,13 @@ class _emoticons extends \IPS\Dispatcher\Controller
|
||||
\IPS\Db::i()->delete( 'core_emoticons', array( 'emo_set=?', $set ) );
|
||||
\IPS\Lang::deleteCustom( 'core', 'core_emoticon_group_'. $set );
|
||||
|
||||
unset( \IPS\Data\Store::i()->emoticons );
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => time() ), array( 'conf_key=?', 'emoji_cache' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
|
||||
/* Clear guest page caches */
|
||||
\IPS\Data\Cache::i()->clearAll();
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=editor&controller=emoticons' ), 'saved' );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=editor&controller=emoticons&tab=custom' ), 'saved' );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -389,7 +452,7 @@ class _emoticons extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
\IPS\Lang::saveCustom( 'core', \IPS\Request::i()->key, $values['emoticons_add_newgroup'] );
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=editor&controller=emoticons' ), 'saved' );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=editor&controller=emoticons&tab=custom' ), 'saved' );
|
||||
}
|
||||
|
||||
if( \IPS\Request::i()->isAjax() )
|
||||
|
||||
@@ -56,7 +56,7 @@ class _settings extends \IPS\Dispatcher\Controller
|
||||
protected function manage()
|
||||
{
|
||||
/* Work out output */
|
||||
$activeTabContents = call_user_func( array( $this, '_manage'.ucfirst( $this->activeTab ) ) );
|
||||
$activeTabContents = call_user_func( array( $this, '_manage' . mb_ucfirst( $this->activeTab ) ) );
|
||||
|
||||
/* If this is an AJAX request, just return it */
|
||||
if( \IPS\Request::i()->isAjax() )
|
||||
|
||||
@@ -107,7 +107,7 @@ class _toolbar extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
$dummy = new \IPS\Helpers\Form\Editor( 'editor', NULL, FALSE, array( 'autoSaveKey' => md5( uniqid() ), 'allButtons' => TRUE ) );
|
||||
$dummy = new \IPS\Helpers\Form\Editor( 'editor', NULL, FALSE, array( 'autoSaveKey' => md5( mt_rand() ), 'allButtons' => TRUE ) );
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__core_editor_toolbar');
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js('admin_customization.js', 'core', 'admin') );
|
||||
@@ -156,8 +156,7 @@ class _toolbar extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => json_encode( $save ) ), array( 'conf_key=?', 'ckeditor_toolbars' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
\IPS\Settings::i()->changeValues( array( 'ckeditor_toolbars' => json_encode( $save ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,10 +171,22 @@ class _toolbar extends \IPS\Dispatcher\Controller
|
||||
$current = json_decode( \IPS\Settings::i()->ckeditor_permissions, TRUE );
|
||||
|
||||
/* Get areas */
|
||||
$areas = array_combine( array_keys( \IPS\Application::allExtensions( 'core', 'EditorLocations', FALSE ) ), array_map( function( $v )
|
||||
{
|
||||
return 'editor__' . $v;
|
||||
}, array_keys( \IPS\Application::allExtensions( 'core', 'EditorLocations', FALSE ) ) ) );
|
||||
$filteredAreas = array_filter(
|
||||
\IPS\Application::allExtensions( 'core', 'EditorLocations', FALSE ),
|
||||
function( $elem ) {
|
||||
return ( !isset( $elem::$buttonLocation ) OR $elem::$buttonLocation !== FALSE );
|
||||
}
|
||||
);
|
||||
$areas = array_combine(
|
||||
array_keys( $filteredAreas ),
|
||||
array_map(
|
||||
function( $v )
|
||||
{
|
||||
return 'editor__' . $v;
|
||||
},
|
||||
array_keys( $filteredAreas )
|
||||
)
|
||||
);
|
||||
|
||||
/* Build Form */
|
||||
$b64Button = base64_encode( $button );
|
||||
@@ -255,8 +266,7 @@ class _toolbar extends \IPS\Dispatcher\Controller
|
||||
'groups' => $values['editor_permission_groups'],
|
||||
'areas' => $values['editor_permission_areas'],
|
||||
);
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => json_encode( $current ) ), array( 'conf_key=?', 'ckeditor_permissions' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
\IPS\Settings::i()->changeValues( array( 'ckeditor_permissions' => json_encode( $current ) ) );
|
||||
|
||||
/* Clear guest page caches */
|
||||
\IPS\Data\Cache::i()->clearAll();
|
||||
@@ -308,14 +318,13 @@ class _toolbar extends \IPS\Dispatcher\Controller
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
/* Write */
|
||||
$key = 'custom-' . md5( uniqid() );
|
||||
$key = 'custom-' . md5( mt_rand() );
|
||||
$this->_saveCustomPlugin( $key, $values );
|
||||
|
||||
/* Save */
|
||||
$extraPlugins = explode( ',', \IPS\Settings::i()->ckeditor_extraPlugins );
|
||||
$extraPlugins[] = $key;
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => implode( ',', array_filter( array_unique( $extraPlugins ) ) ) ), array( 'conf_key=?', 'ckeditor_extraPlugins' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
\IPS\Settings::i()->changeValues( array( 'ckeditor_extraPlugins' => implode( ',', array_filter( array_unique( $extraPlugins ) ) ) ) );
|
||||
|
||||
/* Clear guest page caches */
|
||||
\IPS\Data\Cache::i()->clearAll();
|
||||
@@ -461,8 +470,7 @@ class _toolbar extends \IPS\Dispatcher\Controller
|
||||
$extraPlugins = explode( ',', \IPS\Settings::i()->ckeditor_extraPlugins );
|
||||
$extraPlugins[] = $name;
|
||||
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => implode( ',', array_filter( array_unique( $extraPlugins ) ) ) ), array( 'conf_key=?', 'ckeditor_extraPlugins' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
\IPS\Settings::i()->changeValues( array( 'ckeditor_extraPlugins' => implode( ',', array_filter( array_unique( $extraPlugins ) ) ) ) );
|
||||
|
||||
/* Clear guest page caches */
|
||||
\IPS\Data\Cache::i()->clearAll();
|
||||
@@ -540,8 +548,7 @@ class _toolbar extends \IPS\Dispatcher\Controller
|
||||
$settingClasses = \IPS\Settings::i()->editor_allowed_classes ? explode( ',', \IPS\Settings::i()->editor_allowed_classes ) : array();
|
||||
$settingClasses = array_unique( array_merge( $settingClasses, $cssClasses ) );
|
||||
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => implode( ',', $settingClasses ) ), array( 'conf_key=?', 'editor_allowed_classes' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
\IPS\Settings::i()->changeValues( array( 'editor_allowed_classes' => implode( ',', $settingClasses ) ) );
|
||||
}
|
||||
|
||||
/* Figure out data-controllers classes */
|
||||
@@ -563,8 +570,7 @@ class _toolbar extends \IPS\Dispatcher\Controller
|
||||
$settingControllers = \IPS\Settings::i()->editor_allowed_datacontrollers ? explode( ',', \IPS\Settings::i()->editor_allowed_datacontrollers ) : array();
|
||||
$settingControllers = array_unique( array_merge( $settingControllers, $dataControllers ) );
|
||||
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => implode( ',', $settingControllers ) ), array( 'conf_key=?', 'editor_allowed_datacontrollers' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
\IPS\Settings::i()->changeValues( array( 'editor_allowed_datacontrollers' => implode( ',', $settingControllers ) ) );
|
||||
}
|
||||
|
||||
$attributes = json_encode( $attributes );
|
||||
@@ -791,8 +797,7 @@ JS;
|
||||
unset( $extraPlugins[ $k ] );
|
||||
}
|
||||
}
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => implode( ',', array_filter( array_unique( $extraPlugins ) ) ) ), array( 'conf_key=?', 'ckeditor_extraPlugins' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
\IPS\Settings::i()->changeValues( array( 'ckeditor_extraPlugins' => implode( ',', array_filter( array_unique( $extraPlugins ) ) ) ) );
|
||||
|
||||
/* Clear guest page caches */
|
||||
\IPS\Data\Cache::i()->clearAll();
|
||||
@@ -850,11 +855,10 @@ JS;
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => '' ), array( 'conf_key=?', 'ckeditor_extraPlugins' ) );
|
||||
\IPS\Settings::i()->changeValues( array( 'ckeditor_extraPlugins' => '' ) );
|
||||
}
|
||||
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => '' ), array( 'conf_key=?', 'ckeditor_toolbars' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
\IPS\Settings::i()->changeValues( array( 'ckeditor_toolbars' => '' ) );
|
||||
|
||||
/* Clear guest page caches */
|
||||
\IPS\Data\Cache::i()->clearAll();
|
||||
|
||||
@@ -769,6 +769,9 @@ class _languages extends \IPS\Node\Controller
|
||||
$data = array( 'apps' => array(), 'id' => $insertId );
|
||||
return array( $data, \IPS\Member::loggedIn()->language()->get('processing') );
|
||||
}
|
||||
|
||||
/* Only import language strings from applications we have installed */
|
||||
$applications = array_keys( \IPS\Application::applications() );
|
||||
|
||||
/* Move to correct app */
|
||||
$appKey = NULL;
|
||||
@@ -777,7 +780,7 @@ class _languages extends \IPS\Node\Controller
|
||||
while ( $xml->read() )
|
||||
{
|
||||
$appKey = $xml->getAttribute('key');
|
||||
if ( !array_key_exists( $appKey, $data['apps'] ) )
|
||||
if ( !array_key_exists( $appKey, $data['apps'] ) AND in_array( $appKey, $applications ) )
|
||||
{
|
||||
/* Get version */
|
||||
$version = $xml->getAttribute('version');
|
||||
@@ -940,7 +943,8 @@ class _languages extends \IPS\Node\Controller
|
||||
{
|
||||
\IPS\Member::updateAllMembers( array( 'language' => \IPS\Request::i()->id ) );
|
||||
}
|
||||
\IPS\Session::i()->log( 'acplogs__members_language_reset', array( \IPS\Lang::load( \IPS\Request::i()->id )->title => FALSE ) );
|
||||
|
||||
\IPS\Session::i()->log( 'acplogs__members_language_reset', array( \IPS\Lang::load( \IPS\Request::i()->id ?: \IPS\Lang::defaultLanguage() )->title => FALSE ) );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=languages&controller=languages' ), 'reset' );
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ class _devices extends \IPS\Dispatcher\Controller
|
||||
$userAgent = $device->userAgent();
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'member_names_device', FALSE, array( 'sprintf' => array( $member->name, $userAgent->platform ) ) );
|
||||
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( "app=core&module=members&controller=members" ), 'members' );
|
||||
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( "app=core&module=members&controller=members&do=edit&id={$member->member_id}" ), $member->name );
|
||||
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( "app=core&module=members&controller=members&do=view&id={$member->member_id}" ), $member->name );
|
||||
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( "app=core&module=members&controller=devices&do=member&id={$member->member_id}" ), 'members_devices' );
|
||||
\IPS\Output::i()->breadcrumb[] = array( NULL, $userAgent );
|
||||
|
||||
@@ -137,7 +137,7 @@ class _devices extends \IPS\Dispatcher\Controller
|
||||
'view' => array(
|
||||
'title' => 'view',
|
||||
'icon' => 'search',
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=members&controller=members&do=edit' )->setQueryString( 'id', $row['member_id'] ),
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=members&controller=members&do=view' )->setQueryString( 'id', $row['member_id'] ),
|
||||
),
|
||||
);
|
||||
};
|
||||
@@ -234,7 +234,7 @@ class _devices extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'members' )->deviceTable( $table );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'member_names_devices', FALSE, array( 'sprintf' => array( $member->name ) ) );
|
||||
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( "app=core&module=members&controller=members" ), 'members' );
|
||||
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( "app=core&module=members&controller=members&do=edit&id={$member->member_id}" ), $member->name );
|
||||
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( "app=core&module=members&controller=members&do=view&id={$member->member_id}" ), $member->name );
|
||||
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( "app=core&module=members&controller=devices&do=member&id={$member->member_id}" ), 'members_devices' );
|
||||
}
|
||||
|
||||
@@ -247,11 +247,15 @@ class _devices extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
try
|
||||
{
|
||||
$device = \IPS\Member\Device::loadAndAuthenticate( \IPS\Request::i()->device, \IPS\Member::load( \IPS\Request::i()->member ) );
|
||||
$member = \IPS\Member::load( \IPS\Request::i()->member );
|
||||
$device = \IPS\Member\Device::loadAndAuthenticate( \IPS\Request::i()->device, $member );
|
||||
$device->login_key = NULL;
|
||||
$device->save();
|
||||
|
||||
\IPS\Db::i()->delete( 'core_sessions', array( 'member_id=? AND browser=?', $device->member_id, $device->user_agent ) );
|
||||
$member->logHistory( 'core', 'login', array( 'type' => 'logout', 'device' => $device->device_key ) );
|
||||
\IPS\Session::i()->log( 'acplog__members_disabled_autologin', array( $member->name => FALSE ) );
|
||||
|
||||
\IPS\Session\Store::i()->deleteByMember( $device->member_id, $device->user_agent );
|
||||
}
|
||||
catch ( \Exception $e ) { }
|
||||
|
||||
|
||||
@@ -65,7 +65,8 @@ class _groups extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
if ( $row['g_id'] == \IPS\Settings::i()->guest_group )
|
||||
{
|
||||
$onlineGuests = \IPS\Db::i()->select( 'COUNT(*)', 'core_sessions', array( 'login_type=? AND running_time>?', \IPS\Session\Front::LOGIN_TYPE_GUEST, \IPS\DateTime::create()->sub( new \DateInterval( 'PT30M' ) )->getTimeStamp() ) )->first();
|
||||
$onlineGuests = \IPS\Session\Store::i()->getOnlineUsers( \IPS\Session\Store::ONLINE_GUESTS | \IPS\Session\Store::ONLINE_COUNT_ONLY );
|
||||
|
||||
return \IPS\Member::loggedIn()->language()->addToStack( 'online_guests', FALSE, array( 'pluralize' => array( $onlineGuests ) ) );
|
||||
}
|
||||
|
||||
@@ -88,8 +89,20 @@ class _groups extends \IPS\Dispatcher\Controller
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=members&controller=groups&do=form' ),
|
||||
);
|
||||
}
|
||||
|
||||
/* Show an extra warning if we are going to delete a group that Commerce intends to move subscribers back to */
|
||||
if( \IPS\Db::i()->checkForColumn( 'core_members', 'cm_return_group' ) )
|
||||
{
|
||||
$warnGroups = array();
|
||||
|
||||
try
|
||||
{
|
||||
$warnGroups = iterator_to_array( \IPS\Db::i()->select( 'DISTINCT(cm_return_group)', 'core_members' ) );
|
||||
}
|
||||
catch( \Exception $e ){}
|
||||
}
|
||||
|
||||
$table->rowButtons = function( $row )
|
||||
$table->rowButtons = function( $row ) use ( $warnGroups )
|
||||
{
|
||||
$return = array();
|
||||
|
||||
@@ -137,7 +150,9 @@ class _groups extends \IPS\Dispatcher\Controller
|
||||
'icon' => 'times-circle',
|
||||
'title' => 'delete',
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=members&controller=groups&do=delete&id=' ) . $row['g_id'],
|
||||
'data' => \IPS\Db::i()->select( 'COUNT(*)', 'core_members', array( 'member_group_id=?', $row['g_id'] ) )->first() ? array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack( "core_group_{$row['g_id']}" ) ) : array( 'delete' => '' ),
|
||||
'data' => \IPS\Db::i()->select( 'COUNT(*)', 'core_members', array( 'member_group_id=?', $row['g_id'] ) )->first() ?
|
||||
array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack( "core_group_{$row['g_id']}" ) ) :
|
||||
array( 'delete' => '', 'delete-warning' => ( in_array( $row['g_id'], $warnGroups ) ) ? \IPS\Member::loggedIn()->language()->addToStack( "nexus_dont_delete_group", FALSE, array( 'sprintf' => array( \IPS\Member\Group::load( \IPS\Settings::i()->member_group )->name ) ) ) : '' ),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -300,7 +315,19 @@ class _groups extends \IPS\Dispatcher\Controller
|
||||
|
||||
if ( isset( $current[ $class::$permApp ][ $class::$permType ] ) )
|
||||
{
|
||||
$matrix->rows = call_user_func( $callback, $current[ $class::$permApp ][ $class::$permType ], $group );
|
||||
try
|
||||
{
|
||||
$matrix->rows = call_user_func( $callback, $current[ $class::$permApp ][ $class::$permType ], $group );
|
||||
}
|
||||
catch( \UnderflowException $e )
|
||||
{
|
||||
if( $e->getCode() != 199 )
|
||||
{
|
||||
throw $e;
|
||||
}
|
||||
|
||||
\IPS\Output::i()->error( 'generic_error', '4T382/1', 500, $e->getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
/* Add the matrix */
|
||||
@@ -358,7 +385,7 @@ class _groups extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Copy */
|
||||
$newGroup = clone $group;
|
||||
\IPS\Session::i()->log( 'acplog__groups_copied', array( $newGroup->name => FALSE ) );
|
||||
\IPS\Session::i()->log( 'acplog__groups_copied', array( "core_group_". $newGroup->g_id => TRUE ) );
|
||||
|
||||
/* And redirect */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=members&controller=groups&do=form&id={$newGroup->g_id}" ) );
|
||||
@@ -372,17 +399,15 @@ class _groups extends \IPS\Dispatcher\Controller
|
||||
public function delete()
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'groups_delete' );
|
||||
|
||||
/* Make sure the user confirmed the deletion */
|
||||
\IPS\Request::i()->confirmedDelete();
|
||||
|
||||
/* Load group */
|
||||
try
|
||||
{
|
||||
$group = \IPS\Member\Group::load( \IPS\Request::i()->id );
|
||||
$count = \IPS\Db::i()->select( 'COUNT(*)', 'core_members', array( 'member_group_id=?', $group->g_id ) )->first();
|
||||
|
||||
/* Any members in it? */
|
||||
if ( \IPS\Db::i()->select( 'COUNT(*)', 'core_members', array( 'member_group_id=?', $group->g_id ) )->first() )
|
||||
if ( $count )
|
||||
{
|
||||
/* Create the options, but don't let the admin move members in the group back into this same group */
|
||||
$groupOptions = \IPS\Member\Group::groups( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'members', 'member_move_admin2' ), FALSE );
|
||||
@@ -402,6 +427,11 @@ class _groups extends \IPS\Dispatcher\Controller
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Make sure the user confirmed the deletion */
|
||||
\IPS\Request::i()->confirmedDelete();
|
||||
}
|
||||
|
||||
/* remove this from members secondary groups column */
|
||||
foreach ( new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'core_members', \IPS\Db::i()->findInSet( 'mgroup_others', array( $group->g_id ) ) ), 'IPS\Member') AS $member )
|
||||
@@ -416,11 +446,13 @@ class _groups extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
$member->mgroup_others = implode( ',', array_filter( $secondaryGroups ) );
|
||||
$member->save();
|
||||
\IPS\Db::i()->update( 'core_members', array( 'mgroup_others' => implode( ',', array_filter( $secondaryGroups ) ) ), array( 'member_id=?', $member->member_id ) );
|
||||
}
|
||||
|
||||
\IPS\Session::i()->log( 'acplog__groups_deleted', array( $group->name => FALSE ) );
|
||||
$name = $group->name;
|
||||
\IPS\Member::loggedIn()->language()->parseOutputForDisplay( $name );
|
||||
|
||||
\IPS\Session::i()->log( 'acplog__groups_deleted', array( $name => FALSE ) );
|
||||
$group->delete();
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Profile Completion
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 04 Jan 2018
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\admin\membersettings;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Profile Completion
|
||||
*/
|
||||
class _profilecompletion extends \IPS\Node\Controller
|
||||
{
|
||||
/**
|
||||
* Node Class
|
||||
*/
|
||||
protected $nodeClass = '\IPS\Member\ProfileStep';
|
||||
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'profilefields_manage' );
|
||||
parent::execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function manage()
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'members' )->profileCompleteBlurb();
|
||||
parent::manage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable quick registration
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function enableQuickRegister()
|
||||
{
|
||||
\IPS\Settings::i()->changeValues( array( 'quick_register' => 1 ) );
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=membersettings&controller=profiles&tab=profilecompletion' ), 'profile_complete_quick_register_off_enabled' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Step Form
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function form()
|
||||
{
|
||||
$form = new \IPS\Helpers\Form;
|
||||
if ( isset( \IPS\Request::i()->id ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$step = \IPS\Member\ProfileStep::load( \IPS\Request::i()->id );
|
||||
}
|
||||
catch( \OutOFRangeException $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C360/1', 404, '' );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$step = new \IPS\Member\ProfileStep;
|
||||
}
|
||||
|
||||
$step->form( $form );
|
||||
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$values = $step->formatFormValues( $values );
|
||||
|
||||
$step->extension = \IPS\Member\ProfileStep::findExtensionFromAction( $values['step_completion_act'] );
|
||||
if ( isset( $values['step_required'] ) )
|
||||
{
|
||||
$step->required = $values['step_required'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$step->required = FALSE;
|
||||
}
|
||||
$step->completion_act = $values['step_completion_act'];
|
||||
$step->subcompletion_act = $values['step_subcompletion_act'];
|
||||
$step->save();
|
||||
|
||||
$step->postSaveForm( $values );
|
||||
|
||||
if ( method_exists( $step->extension, 'postAcpSave' ) )
|
||||
{
|
||||
$step->extension->postAcpSave( $step, $values );
|
||||
}
|
||||
|
||||
\IPS\Member::updateAllMembers( array( "members_bitoptions2 = members_bitoptions2 & ~" . \IPS\Member::$bitOptions['members_bitoptions']['members_bitoptions2']['profile_completed'] ) );
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=membersettings&controller=profiles&tab=profilecompletion" ), 'saved' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'profile_completion' );
|
||||
\IPS\Output::i()->output = $form;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Profile Fields and Settings
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 09 Apr 2013
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\admin\membersettings;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Profile Fields and Settings
|
||||
*/
|
||||
class _profilefields extends \IPS\Node\Controller
|
||||
{
|
||||
/**
|
||||
* Node Class
|
||||
*/
|
||||
protected $nodeClass = '\IPS\core\ProfileFields\Group';
|
||||
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'profilefields_manage' );
|
||||
parent::execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Root Buttons
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function _getRootButtons()
|
||||
{
|
||||
$nodeClass = $this->nodeClass;
|
||||
|
||||
if ( $nodeClass::canAddRoot() )
|
||||
{
|
||||
$add = array(
|
||||
'icon' => 'plus',
|
||||
'title' => 'add',
|
||||
'link' => $this->url->setQueryString( 'do', 'form' ),
|
||||
'data' => ( $nodeClass::$modalForms ? array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('add') ) : array() )
|
||||
);
|
||||
|
||||
return array( 'add' => $add );
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Profile Fields and Settings
|
||||
* @brief Profile settings gateway
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 09 Apr 2013
|
||||
* @since 08 Jan 2018
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\admin\membersettings;
|
||||
@@ -18,326 +18,51 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
}
|
||||
|
||||
/**
|
||||
* Profile Fields and Settings
|
||||
* Profile settings gateway
|
||||
*/
|
||||
class _profiles extends \IPS\Node\Controller
|
||||
class _profiles extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* Node Class
|
||||
*/
|
||||
protected $nodeClass = '\IPS\core\ProfileFields\Group';
|
||||
|
||||
/**
|
||||
* Execute
|
||||
* Call
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'profilefields_manage' );
|
||||
parent::execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
public function __call( $method, $args )
|
||||
{
|
||||
/* Init */
|
||||
$activeTab = \IPS\Request::i()->tab ?: 'fields';
|
||||
$activeTabContents = '';
|
||||
$tabs = array( 'fields' => 'profile_fields' );
|
||||
|
||||
$activeTab = \IPS\Request::i()->tab ?: 'profilefields';
|
||||
$activeTabContents = '';
|
||||
$tabs = array();
|
||||
|
||||
/* Add a tab for fields and completion */
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'membersettings', 'profilesfields_manage' ) )
|
||||
{
|
||||
$tabs['profilefields'] = 'profile_fields';
|
||||
$tabs['profilecompletion'] = 'profile_completion';
|
||||
}
|
||||
|
||||
/* Add a tab for settings */
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'membersettings', 'profiles_manage' ) )
|
||||
{
|
||||
$tabs['settings'] = 'profile_settings';
|
||||
$tabs['completion'] = 'profile_completion';
|
||||
}
|
||||
|
||||
$method = '_tab' . ucwords( $activeTab );
|
||||
if ( method_exists( $this, $method ) )
|
||||
{
|
||||
$activeTabContents = (string) $this->$method();
|
||||
}
|
||||
|
||||
/* Display */
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('module__core_profile');
|
||||
if( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->output = $activeTabContents;
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global' )->tabs( $tabs, $activeTab, $activeTabContents, \IPS\Http\Url::internal( "app=core&module=membersettings&controller=profiles" ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fields Tab
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function _tabFields()
|
||||
{
|
||||
parent::manage();
|
||||
return \IPS\Output::i()->output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Settings Tab
|
||||
*
|
||||
* @return \IPS\Helpers\Form
|
||||
*/
|
||||
protected function _tabSettings()
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'profiles_manage' );
|
||||
|
||||
$form = new \IPS\Helpers\Form;
|
||||
|
||||
$form->addHeader( 'photos' );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'allow_gravatars', \IPS\Settings::i()->allow_gravatars ) );
|
||||
|
||||
if( \IPS\Image::canWriteText() )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'letter_photos', \IPS\Settings::i()->letter_photos, FALSE, array( 'options' => array( 'default' => 'letterphoto_default', 'letters' => 'letterphoto_letters' ) ) ) );
|
||||
$tabs['profilesettings'] = 'profile_settings';
|
||||
}
|
||||
|
||||
$form->addHeader( 'usernames' );
|
||||
$form->add( new \IPS\Helpers\Form\Custom( 'user_name_length', array( \IPS\Settings::i()->min_user_name_length, \IPS\Settings::i()->max_user_name_length ), FALSE, array(
|
||||
'getHtml' => function( $field ) {
|
||||
return \IPS\Theme::i()->getTemplate('members')->usernameLengthSetting( $field->name, $field->value );
|
||||
}
|
||||
),
|
||||
function( $val )
|
||||
{
|
||||
if ( $val[0] < 1 )
|
||||
{
|
||||
throw new \DomainException('user_name_length_too_low');
|
||||
}
|
||||
if ( $val[1] > 255 )
|
||||
{
|
||||
throw new \DomainException('user_name_length_too_high');
|
||||
}
|
||||
if ( $val[0] > $val[1] )
|
||||
{
|
||||
throw new \DomainException('user_name_length_no_match');
|
||||
}
|
||||
} ) );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'username_characters', \IPS\Settings::i()->username_characters, FALSE, array( 'max' => 255 ) ) );
|
||||
$form->addHeader( 'signatures' );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'signatures_enabled', \IPS\Settings::i()->signatures_enabled ) );
|
||||
$form->addHeader( 'statuses_profile_comments' );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'profile_comments', \IPS\Settings::i()->profile_comments, FALSE, array( 'togglesOn' => array( 'profile_comment_approval' ) ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'profile_comment_approval', \IPS\Settings::i()->profile_comment_approval, FALSE, array(), NULL, NULL, NULL, 'profile_comment_approval' ) );
|
||||
$form->addHeader( 'profile_settings_birthdays' );
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'profile_birthday_type', \IPS\Settings::i()->profile_birthday_type, TRUE, array(
|
||||
'options' => array( 'public' => 'profile_birthday_type_public', 'private' => 'profile_birthday_type_private', 'none' => 'profile_birthday_type_none' )
|
||||
), NULL, NULL, NULL, 'profile_birthday_type' ) );
|
||||
|
||||
if( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'profiles', 'member_history_prune' ) )
|
||||
{
|
||||
$form->addHeader( 'profile_member_history' );
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'prune_member_history', \IPS\Settings::i()->prune_member_history, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'never' ), NULL, \IPS\Member::loggedIn()->language()->addToStack('after'), \IPS\Member::loggedIn()->language()->addToStack('days'), 'prune_member_history' ) );
|
||||
}
|
||||
|
||||
$form->addHeader( 'profile_settings_ignore' );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'ignore_system_on', \IPS\Settings::i()->ignore_system_on, FALSE, array(), NULL, NULL, NULL, 'ignore_system_on' ) );
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$values['min_user_name_length'] = $values['user_name_length'][0];
|
||||
$values['max_user_name_length'] = $values['user_name_length'][1];
|
||||
unset( $values['user_name_length'] );
|
||||
/* Route */
|
||||
$classname = 'IPS\core\modules\admin\membersettings\\' . $activeTab;
|
||||
$class = new $classname;
|
||||
$class->url = \IPS\Http\Url::internal("app=core&module=membersettings&controller=profiles&tab={$activeTab}");
|
||||
$class->execute();
|
||||
|
||||
$form->saveAsSettings( $values );
|
||||
\IPS\Session::i()->log( 'acplog__profile_settings' );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=membersettings&controller=profiles&tab=settings' ), 'saved' );
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Completion Tab
|
||||
*
|
||||
* @return \IPS\Helpers\Form
|
||||
*/
|
||||
protected function _tabCompletion()
|
||||
{
|
||||
/* Is the quick register function disabled? */
|
||||
if ( ! \IPS\Settings::i()->quick_register )
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate( 'members' )->quickRegisterDisabled();
|
||||
}
|
||||
|
||||
$table = new \IPS\Helpers\Table\Db( 'core_profile_steps', \IPS\Http\Url::internal( 'app=core&module=membersettings&controller=profiles&tab=completion' ) );
|
||||
$table->langPrefix = 'profile_acp_table_';
|
||||
$table->include = array( 'step_extension', 'step_required' );
|
||||
$table->rootButtons = array(
|
||||
array(
|
||||
'icon' => 'plus',
|
||||
'title' => 'add',
|
||||
'link' => \IPS\Http\Url::internal( "app=core&module=membersettings&controller=profiles&do=step" )
|
||||
)
|
||||
);
|
||||
$table->parsers = array(
|
||||
'step_extension' => function( $val, $row )
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate( 'members' )->profileCompleteTitle( $row );
|
||||
},
|
||||
'step_required' => function( $val ) {
|
||||
if ( $val )
|
||||
{
|
||||
return '✓';
|
||||
}
|
||||
else
|
||||
{
|
||||
return '✗';
|
||||
}
|
||||
}
|
||||
);
|
||||
$table->rowButtons = function( $row )
|
||||
{
|
||||
return array(
|
||||
'edit' => array(
|
||||
'title' => 'edit',
|
||||
'icon' => 'pencil',
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=membersettings&controller=profiles&do=step&id=' . $row['step_id'] )
|
||||
),
|
||||
'delete' => array(
|
||||
'title' => 'delete',
|
||||
'icon' => 'times-circle',
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=membersettings&controller=profiles&do=deleteStep&id=' . $row['step_id'] ),
|
||||
'data' => array( 'delete' => '' )
|
||||
),
|
||||
);
|
||||
};
|
||||
$output = \IPS\Output::i()->output;
|
||||
|
||||
return \IPS\Theme::i()->getTemplate( 'members' )->profileCompleteBlurb() . $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable quick registration
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function enableQuickRegister()
|
||||
{
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => 1 ), array( 'conf_key=?', 'quick_register' ) );
|
||||
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=membersettings&controller=profiles&tab=completion' ), 'profile_complete_quick_register_off_enabled' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Step Form
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function step()
|
||||
{
|
||||
$form = new \IPS\Helpers\Form;
|
||||
if ( isset( \IPS\Request::i()->id ) )
|
||||
if ( $method !== 'manage' or \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
try
|
||||
{
|
||||
$step = \IPS\Member\ProfileStep::load( \IPS\Request::i()->id );
|
||||
}
|
||||
catch( \OutOFRangeException $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C360/1', 404, '' );
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
$step = new \IPS\Member\ProfileStep;
|
||||
}
|
||||
|
||||
$step->form( $form );
|
||||
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$values = $step->formatFormValues( $values );
|
||||
|
||||
$step->extension = \IPS\Member\ProfileStep::findExtensionFromAction( $values['step_completion_act'] );
|
||||
if ( isset( $values['step_required'] ) )
|
||||
{
|
||||
$step->required = $values['step_required'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$step->required = FALSE;
|
||||
}
|
||||
$step->completion_act = $values['step_completion_act'];
|
||||
$step->subcompletion_act = $values['step_subcompletion_act'];
|
||||
$step->save();
|
||||
|
||||
$step->postSaveForm( $values );
|
||||
|
||||
if ( method_exists( $step->extension, 'postAcpSave' ) )
|
||||
{
|
||||
$step->extension->postAcpSave( $step, $values );
|
||||
}
|
||||
|
||||
\IPS\Member::updateAllMembers( array( "members_bitoptions2 = members_bitoptions2 & ~" . \IPS\Member::$bitOptions['members_bitoptions']['members_bitoptions2']['profile_completed'] ) );
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=membersettings&controller=profiles&tab=completion" ), 'saved' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal( 'app=core&module=membersettings&controller=profiles&tab=completion' ), \IPS\Member::loggedIn()->language()->addToStack('profile_completion') );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'profile_completion' );
|
||||
\IPS\Output::i()->output = $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete Step
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function deleteStep()
|
||||
{
|
||||
try
|
||||
{
|
||||
$step = \IPS\Member\ProfileStep::load( \IPS\Request::i()->id );
|
||||
}
|
||||
catch( \OutOfRangeException $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C360/2', 404, '' );
|
||||
}
|
||||
|
||||
/* Make sure the user confirmed the deletion */
|
||||
\IPS\Request::i()->confirmedDelete();
|
||||
|
||||
$step->delete();
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=membersettings&controller=profiles&tab=completion" ), 'deleted' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Root Buttons
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function _getRootButtons()
|
||||
{
|
||||
$nodeClass = $this->nodeClass;
|
||||
|
||||
if ( $nodeClass::canAddRoot() )
|
||||
{
|
||||
$add = array(
|
||||
'icon' => 'plus',
|
||||
'title' => 'add',
|
||||
'link' => $this->url->setQueryString( 'do', 'form' ),
|
||||
'data' => ( $nodeClass::$modalForms ? array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('add') ) : array() )
|
||||
);
|
||||
|
||||
|
||||
return array( 'add' => $add );
|
||||
}
|
||||
return array();
|
||||
\IPS\Output::i()->output = '';
|
||||
|
||||
/* Output */
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('module__core_profile');
|
||||
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'global', 'core' )->tabs( $tabs, $activeTab, $output, \IPS\Http\Url::internal( "app=core&module=membersettings&controller=profiles" ) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Profile Settings
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 08 Jan 2018
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\admin\membersettings;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Profile Settings
|
||||
*/
|
||||
class _profilesettings extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'profiles_manage' );
|
||||
parent::execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function manage()
|
||||
{
|
||||
$form = new \IPS\Helpers\Form;
|
||||
|
||||
$form->addHeader( 'photos' );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'allow_gravatars', \IPS\Settings::i()->allow_gravatars ) );
|
||||
|
||||
if( \IPS\Image::canWriteText() )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'letter_photos', \IPS\Settings::i()->letter_photos, FALSE, array( 'options' => array( 'default' => 'letterphoto_default', 'letters' => 'letterphoto_letters' ) ) ) );
|
||||
}
|
||||
|
||||
$form->addHeader( 'usernames' );
|
||||
$form->add( new \IPS\Helpers\Form\Custom( 'user_name_length', array( \IPS\Settings::i()->min_user_name_length, \IPS\Settings::i()->max_user_name_length ), FALSE, array(
|
||||
'getHtml' => function( $field ) {
|
||||
return \IPS\Theme::i()->getTemplate('members')->usernameLengthSetting( $field->name, $field->value );
|
||||
}
|
||||
),
|
||||
function( $val )
|
||||
{
|
||||
if ( $val[0] < 1 )
|
||||
{
|
||||
throw new \DomainException('user_name_length_too_low');
|
||||
}
|
||||
if ( $val[1] > 255 )
|
||||
{
|
||||
throw new \DomainException('user_name_length_too_high');
|
||||
}
|
||||
if ( $val[0] > $val[1] )
|
||||
{
|
||||
throw new \DomainException('user_name_length_no_match');
|
||||
}
|
||||
} ) );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'username_characters', \IPS\Settings::i()->username_characters, FALSE, array( 'max' => 255 ) ) );
|
||||
$form->addHeader( 'signatures' );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'signatures_enabled', \IPS\Settings::i()->signatures_enabled ) );
|
||||
|
||||
/* Status updates */
|
||||
$options = array(
|
||||
0 => 'status_updates_disabled',
|
||||
1 => 'status_updates_enabled_nomem',
|
||||
2 => 'status_updates_enabled_mem'
|
||||
);
|
||||
|
||||
$default = \IPS\Settings::i()->profile_comments ? ( \IPS\Settings::i()->status_updates_mem_enable ? 2 : 1 ) : 0;
|
||||
|
||||
$form->addHeader( 'statuses_profile_comments' );
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'profile_comments', $default, FALSE, array( 'options' => $options, 'toggles' => array( 1 => array( 'profile_comment_approval' ), 2 => array( 'profile_comment_approval' ) ) ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'profile_comment_approval', \IPS\Settings::i()->profile_comment_approval, FALSE, array(), NULL, NULL, NULL, 'profile_comment_approval' ) );
|
||||
|
||||
$form->addHeader( 'profile_settings_birthdays' );
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'profile_birthday_type', \IPS\Settings::i()->profile_birthday_type, TRUE, array(
|
||||
'options' => array( 'public' => 'profile_birthday_type_public', 'private' => 'profile_birthday_type_private', 'none' => 'profile_birthday_type_none' )
|
||||
), NULL, NULL, NULL, 'profile_birthday_type' ) );
|
||||
|
||||
if( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'profiles', 'member_history_prune' ) )
|
||||
{
|
||||
$form->addHeader( 'profile_member_history' );
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'prune_member_history', \IPS\Settings::i()->prune_member_history, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'never' ), NULL, \IPS\Member::loggedIn()->language()->addToStack('after'), \IPS\Member::loggedIn()->language()->addToStack('days'), 'prune_member_history' ) );
|
||||
}
|
||||
|
||||
$form->addHeader( 'profile_settings_ignore' );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'ignore_system_on', \IPS\Settings::i()->ignore_system_on, FALSE, array(), NULL, NULL, NULL, 'ignore_system_on' ) );
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$values['min_user_name_length'] = $values['user_name_length'][0];
|
||||
$values['max_user_name_length'] = $values['user_name_length'][1];
|
||||
unset( $values['user_name_length'] );
|
||||
|
||||
$values['status_updates_mem_enable'] = ( $values['profile_comments'] == 2 ) ? 1 : 0;
|
||||
$values['profile_comments'] = ( $values['profile_comments'] > 0 ) ? 1 : 0;
|
||||
|
||||
$form->saveAsSettings( $values );
|
||||
\IPS\Session::i()->log( 'acplog__profile_settings' );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=membersettings&controller=profiles&tab=profilesettings' ), 'saved' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->output = (string) $form;
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Registration
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 18 Jul 2013
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\admin\membersettings;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registration
|
||||
*/
|
||||
class _registration extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'registration_manage' );
|
||||
parent::execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* General Member Settings
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
{
|
||||
$form = $this->getSettingsForm();
|
||||
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
if ( isset( $values['allowed_reg_email'] ) and is_array( $values['allowed_reg_email'] ) )
|
||||
{
|
||||
$values['allowed_reg_email'] = implode( ',', $values['allowed_reg_email'] );
|
||||
}
|
||||
|
||||
if ( $values['use_coppa'] OR $values['minimum_age'] )
|
||||
{
|
||||
$values['quick_register'] = 0;
|
||||
}
|
||||
|
||||
$form->saveAsSettings( $values );
|
||||
|
||||
/* Clear guest page caches */
|
||||
\IPS\Data\Cache::i()->clearAll();
|
||||
|
||||
\IPS\Session::i()->log( 'acplogs__general_settings' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('membersettings_registration_title');
|
||||
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'global' )->block( 'membersettings_registration_title', $form );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the settings form
|
||||
*
|
||||
* @return \IPS\Helpers\Form
|
||||
*/
|
||||
protected function getSettingsForm()
|
||||
{
|
||||
$form = new \IPS\Helpers\Form;
|
||||
|
||||
$form->addHeader('registration');
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'allow_reg', \IPS\Settings::i()->allow_reg, FALSE, array( 'togglesOn' => array( 'quick_register', 'new_reg_notify', 'reg_auth_type', 'form_header_coppa', 'use_coppa' ) ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'quick_register', \IPS\Settings::i()->quick_register, FALSE, array(), NULL, NULL, NULL, 'quick_register' ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'new_reg_notify', \IPS\Settings::i()->new_reg_notify, FALSE, array(), NULL, NULL, NULL, 'new_reg_notify' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'reg_auth_type', \IPS\Settings::i()->reg_auth_type, TRUE, array(
|
||||
'options' => array( 'user' => 'reg_auth_type_user', 'admin' => 'reg_auth_type_admin', 'admin_user' => 'reg_auth_type_admin_user', 'none' => 'reg_auth_type_none' ),
|
||||
'toggles' => array( 'user' => array( 'validate_day_prune' ), 'admin_user' => array( 'validate_day_prune' ) )
|
||||
), NULL, NULL, NULL, 'reg_auth_type' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'validate_day_prune', \IPS\Settings::i()->validate_day_prune, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'never' ), NULL, \IPS\Member::loggedIn()->language()->addToStack('after'), \IPS\Member::loggedIn()->language()->addToStack('days'), 'validate_day_prune' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Stack( 'allowed_reg_email', explode( ',', \IPS\Settings::i()->allowed_reg_email ), FALSE, array(), NULL, NULL, NULL ) );
|
||||
|
||||
$form->addHeader('age_requirements');
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'minimum_age', \IPS\Settings::i()->minimum_age, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'any_age', 'unlimitedToggles' => array( 'quick_register' ) ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'use_coppa', \IPS\Settings::i()->use_coppa, FALSE, array( 'togglesOn' => array( 'coppa_fax', 'coppa_address' ), 'togglesOff' => array( 'quick_register' ) ), NULL, NULL, NULL, 'use_coppa' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Tel( 'coppa_fax', \IPS\Settings::i()->coppa_fax, FALSE, array(), NULL, NULL, NULL, 'coppa_fax' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Address( 'coppa_address', \IPS\GeoLocation::buildFromJson( \IPS\Settings::i()->coppa_address ), FALSE, array(), NULL, NULL, NULL, 'coppa_address' ) );
|
||||
|
||||
return $form;
|
||||
}
|
||||
}
|
||||
@@ -123,7 +123,7 @@ class _reputation extends \IPS\Node\Controller
|
||||
}
|
||||
|
||||
$member = \IPS\Member::constructFromData( \IPS\Db::i()->select( '*', 'core_members', $where, 'member_id ASC', 1 )->first() );
|
||||
$names[ $member->member_id ] = '<a>' . htmlentities( $member->name, \IPS\HTMLENTITIES, 'UTF-8', FALSE ) . '</a>';
|
||||
$names[ $member->member_id ] = '<a>' . htmlentities( $member->name, ENT_DISALLOWED, 'UTF-8', FALSE ) . '</a>';
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
@@ -176,6 +176,7 @@ class _reputation extends \IPS\Node\Controller
|
||||
$form = new \IPS\Helpers\Form();
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'reputation_leaderboard_on', \IPS\Settings::i()->reputation_leaderboard_on, FALSE, array( 'togglesOn' => array( 'reputation_leaderboard_default_tab', 'form_header_leaderboard_tabs_leaderboard', 'reputation_show_days_won_trophy', 'reputation_timezone', 'form_header_leaderboard_tabs_members', 'reputation_top_members_overview', 'reputation_overview_max_members', 'reputation_top_members_filters', 'reputation_max_members' ) ), NULL, NULL, NULL, 'reputation_leaderboard_on' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'reputation_leaderboard_default_tab', \IPS\Settings::i()->reputation_leaderboard_default_tab, FALSE, array( 'options' => array( 'leaderboard' => 'leaderboard_tabs_leaderboard', 'history' => 'leaderboard_tabs_history', 'members' => 'leaderboard_tabs_members' ) ), NULL, NULL, NULL, 'reputation_leaderboard_default_tab' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Select( 'leaderboard_excluded_groups', \IPS\Settings::i()->leaderboard_excluded_groups, FALSE, array( 'options' => \IPS\Member\Group::groups( TRUE, FALSE ), 'parse' => 'normal', 'multiple' => TRUE ), NULL, NULL, NULL, 'leaderboard_excluded_groups' ) );
|
||||
$form->addHeader('leaderboard_tabs_leaderboard');
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'reputation_show_days_won_trophy', \IPS\Settings::i()->reputation_show_days_won_trophy, FALSE, array( 'togglesOn' => array() ), NULL, NULL, NULL, 'reputation_show_days_won_trophy' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Timezone( 'reputation_timezone', \IPS\Settings::i()->reputation_timezone, FALSE, array(), NULL, NULL, NULL, 'reputation_timezone' ) );
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief reportedContent
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
|
||||
* @since 07 Dec 2017
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\admin\moderation;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* reportedContent
|
||||
*/
|
||||
class _reportedContent extends \IPS\Node\Controller
|
||||
{
|
||||
/**
|
||||
* Node Class
|
||||
*/
|
||||
protected $nodeClass = '\IPS\core\Reports\Rules';
|
||||
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
/* Add a button for settings */
|
||||
\IPS\Output::i()->sidebar['actions'] = array(
|
||||
'settings' => array(
|
||||
'title' => 'reportedContent_settings',
|
||||
'icon' => 'cog',
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=moderation&controller=reportedContent&do=settings' ),
|
||||
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('reportedContent_settings') )
|
||||
),
|
||||
'types' => array(
|
||||
'title' => 'reportedContent_types',
|
||||
'icon' => 'cog',
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=moderation&controller=reportedContentTypes' )
|
||||
)
|
||||
);
|
||||
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('forms')->blurb( 'automaticmoderation_blurb' );
|
||||
|
||||
if ( ! \IPS\Settings::i()->automoderation_enabled )
|
||||
{
|
||||
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate('forms')->blurb( 'automaticmoderation_disabled_blurb' );
|
||||
}
|
||||
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'reportedContent_manage' );
|
||||
parent::execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Profile Settings
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function settings()
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'reportedContent_manage' );
|
||||
|
||||
$form = new \IPS\Helpers\Form;
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'automoderation_enabled', \IPS\Settings::i()->automoderation_enabled, FALSE, array(), NULL, NULL, NULL, 'automoderation_enabled' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'automoderation_report_again_mins', \IPS\Settings::i()->automoderation_report_again_mins, FALSE, array(), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack('automoderation_report_again_mins_suffix'), 'automoderation_report_again_mins' ) );
|
||||
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$form->saveAsSettings();
|
||||
|
||||
\IPS\Db::i()->update( 'core_tasks', array( 'enabled' => (int) $values['automoderation_enabled'] ), array( '`key`=?', 'automaticmoderation' ) );
|
||||
|
||||
\IPS\Session::i()->log( 'acplog__automoderation_settings' );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=moderation&controller=reportedContent' ), 'saved' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('reportedContent_settings');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('global')->block( 'reportedContent_settings', $form, FALSE );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief reportedContentTypes
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
|
||||
* @since 14 Dec 2017
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\admin\moderation;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* reportedContentTypes
|
||||
*/
|
||||
class _reportedContentTypes extends \IPS\Node\Controller
|
||||
{
|
||||
/**
|
||||
* Node Class
|
||||
*/
|
||||
protected $nodeClass = '\IPS\core\Reports\Types';
|
||||
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'reportedContentTypes_manage' );
|
||||
parent::execute();
|
||||
}
|
||||
}
|
||||
+234
-26
@@ -8,7 +8,7 @@
|
||||
* @since 18 Apr 2013
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\admin\membersettings;
|
||||
namespace IPS\core\modules\admin\moderation;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
@@ -44,7 +44,7 @@ class _spam extends \IPS\Dispatcher\Controller
|
||||
protected function manage()
|
||||
{
|
||||
/* Work out output */
|
||||
$activeTabContents = call_user_func( array( $this, '_manage'.ucfirst( $this->activeTab ) ) );
|
||||
$activeTabContents = call_user_func( array( $this, '_manage' . mb_ucfirst( $this->activeTab ) ) );
|
||||
|
||||
/* If this is an AJAX request, just return it */
|
||||
if( \IPS\Request::i()->isAjax() )
|
||||
@@ -59,24 +59,44 @@ class _spam extends \IPS\Dispatcher\Controller
|
||||
$tabs['flagging'] = 'spamprevention_flagging';
|
||||
$tabs['service'] = 'enhancements__core_SpamMonitoring';
|
||||
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'membersettings', 'qanda_manage' ) )
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'moderation', 'qanda_manage' ) and in_array( \IPS\Login::registrationType(), array( 'normal', 'full' ) ) )
|
||||
{
|
||||
$tabs['qanda'] = 'qanda_settings';
|
||||
}
|
||||
|
||||
/* Add a button for logs */
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'membersettings', 'spam_service_log' ) )
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'moderation', 'spam_service_log' ) )
|
||||
{
|
||||
\IPS\Output::i()->sidebar['actions']['errorLog'] = array(
|
||||
'title' => 'spamlogs',
|
||||
'icon' => 'exclamation-triangle',
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=membersettings&controller=spam&do=serviceLogs' ),
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=moderation&controller=spam&do=serviceLogs' ),
|
||||
);
|
||||
}
|
||||
|
||||
/* Add a button for whitelist */
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'moderation', 'spam_whitelist_manage' ) )
|
||||
{
|
||||
\IPS\Output::i()->sidebar['actions']['whitelist'] = array(
|
||||
'title' => 'spam_whitelist',
|
||||
'icon' => 'shield',
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=moderation&controller=spam&do=whitelist' ),
|
||||
);
|
||||
}
|
||||
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'members', 'membertools_delete' ) )
|
||||
{
|
||||
\IPS\Output::i()->sidebar['actions']['delete_guest_content'] = array(
|
||||
'title' => 'member_delete_guest_content',
|
||||
'icon' => 'trash-o',
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=members&controller=members&do=deleteGuestContent' ),
|
||||
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('member_delete_guest_content') )
|
||||
);
|
||||
}
|
||||
|
||||
/* Display */
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__core_membersettings_spam');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global' )->tabs( $tabs, $this->activeTab, $activeTabContents, \IPS\Http\Url::internal( "app=core&module=membersettings&controller=spam" ) );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__core_moderation_spam');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global' )->tabs( $tabs, $this->activeTab, $activeTabContents, \IPS\Http\Url::internal( "app=core&module=moderation&controller=spam" ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,14 +110,14 @@ class _spam extends \IPS\Dispatcher\Controller
|
||||
switch( $type )
|
||||
{
|
||||
case 'options':
|
||||
return array( 'none' => 'captcha_type_none', 'recaptcha2' => 'captcha_type_recaptcha2', 'recaptcha' => 'captcha_type_recaptcha', 'keycaptcha' => 'captcha_type_keycaptcha' );
|
||||
return array( 'none' => 'captcha_type_none', 'invisible' => 'captcha_type_invisible', 'recaptcha2' => 'captcha_type_recaptcha2', 'keycaptcha' => 'captcha_type_keycaptcha' );
|
||||
break;
|
||||
|
||||
case 'toggles':
|
||||
return array(
|
||||
'none' => array( 'bot_antispam_type_warning' ),
|
||||
'recaptcha2' => array( 'guest_captcha', 'recaptcha2_public_key', 'recaptcha2_private_key' ),
|
||||
'recaptcha' => array( 'guest_captcha', 'recaptcha_public_key', 'recaptcha_private_key' ),
|
||||
'invisible' => array( 'guest_captcha', 'recaptcha2_public_key', 'recaptcha2_private_key' ),
|
||||
'keycaptcha' => array( 'guest_captcha', 'keycaptcha_privatekey' )
|
||||
);
|
||||
break;
|
||||
@@ -121,10 +141,8 @@ class _spam extends \IPS\Dispatcher\Controller
|
||||
), NULL, NULL, NULL, 'bot_antispam_type' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'recaptcha2_public_key', \IPS\Settings::i()->recaptcha2_public_key, FALSE, array(), NULL, NULL, NULL, 'recaptcha2_public_key' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'recaptcha2_private_key', \IPS\Settings::i()->recaptcha2_private_key, FALSE, array(), NULL, NULL, NULL, 'recaptcha2_private_key' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'recaptcha_public_key', \IPS\Settings::i()->recaptcha_public_key, FALSE, array(), NULL, NULL, NULL, 'recaptcha_public_key' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'recaptcha_private_key', \IPS\Settings::i()->recaptcha_private_key, FALSE, array(), NULL, NULL, NULL, 'recaptcha_private_key' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'keycaptcha_privatekey', \IPS\Settings::i()->keycaptcha_privatekey, FALSE, array(), NULL, NULL, NULL, 'keycaptcha_privatekey' ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'guest_captcha', \IPS\Settings::i()->guest_captcha, FALSE, array(), NULL, NULL, \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'members', 'membertools_delete' ) ? ( "<a href='" . \IPS\Http\Url::internal( 'app=core&module=members&controller=members&do=deleteGuestContent' ) . "' data-ipsDialog data-ipsDialog-title='" . \IPS\Member::loggedIn()->language()->addToStack('member_delete_guest_content'). "'>" . \IPS\Member::loggedIn()->language()->addToStack('member_delete_guest_content') . "</a>" ) : '', 'guest_captcha' ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'guest_captcha', \IPS\Settings::i()->guest_captcha, FALSE, array(), NULL, NULL, NULL, 'guest_captcha' ) );
|
||||
|
||||
/* Save values */
|
||||
if ( $form->values() )
|
||||
@@ -179,7 +197,7 @@ class _spam extends \IPS\Dispatcher\Controller
|
||||
$form->addHeader( 'enhancements__core_SpamMonitoring' );
|
||||
|
||||
$disabled = FALSE;
|
||||
if( !$licenseData or !isset( $licenseData['products']['spam'] ) or !$licenseData['products']['spam'] or strtotime( $licenseData['expires'] ) < time() )
|
||||
if( !$licenseData or !isset( $licenseData['products']['spam'] ) or !$licenseData['products']['spam'] or ( !$licenseData['cloud'] AND strtotime( $licenseData['expires'] ) < time() ) )
|
||||
{
|
||||
$disabled = TRUE;
|
||||
if( !\IPS\Settings::i()->ipb_reg_number )
|
||||
@@ -218,7 +236,7 @@ class _spam extends \IPS\Dispatcher\Controller
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'qanda_manage' );
|
||||
|
||||
/* Create the table */
|
||||
$table = new \IPS\Helpers\Table\Db( 'core_question_and_answer', \IPS\Http\Url::internal( 'app=core&module=membersettings&controller=spam&tab=qanda' ) );
|
||||
$table = new \IPS\Helpers\Table\Db( 'core_question_and_answer', \IPS\Http\Url::internal( 'app=core&module=moderation&controller=spam&tab=qanda' ) );
|
||||
$table->include = array( 'qa_question' );
|
||||
$table->joins = array(
|
||||
array( 'select' => 'w.word_custom', 'from' => array( 'core_sys_lang_words', 'w' ), 'where' => "w.word_key=CONCAT( 'core_question_and_answer_', core_question_and_answer.qa_id ) AND w.lang_id=" . \IPS\Member::loggedIn()->language()->id )
|
||||
@@ -234,13 +252,13 @@ class _spam extends \IPS\Dispatcher\Controller
|
||||
$table->quickSearch = array( 'word_custom', 'qa_question' );
|
||||
$table->sortDirection = $table->sortDirection ?: 'asc';
|
||||
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'membersettings', 'qanda_add' ) )
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'moderation', 'qanda_add' ) )
|
||||
{
|
||||
$table->rootButtons = array(
|
||||
'add' => array(
|
||||
'icon' => 'plus',
|
||||
'title' => 'qanda_add_question',
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=membersettings&controller=spam&do=question' ),
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=moderation&controller=spam&do=question' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -249,21 +267,21 @@ class _spam extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$return = array();
|
||||
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'membersettings', 'qanda_edit' ) )
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'moderation', 'qanda_edit' ) )
|
||||
{
|
||||
$return['edit'] = array(
|
||||
'icon' => 'pencil',
|
||||
'title' => 'edit',
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=membersettings&controller=spam&do=question&id=' ) . $row['qa_id'],
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=moderation&controller=spam&do=question&id=' ) . $row['qa_id'],
|
||||
);
|
||||
}
|
||||
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'membersettings', 'qanda_delete' ) )
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'moderation', 'qanda_delete' ) )
|
||||
{
|
||||
$return['delete'] = array(
|
||||
'icon' => 'times-circle',
|
||||
'title' => 'delete',
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=membersettings&controller=spam&do=delete&id=' ) . $row['qa_id'],
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=moderation&controller=spam&do=delete&id=' ) . $row['qa_id'],
|
||||
'data' => array( 'delete' => '' ),
|
||||
);
|
||||
}
|
||||
@@ -326,7 +344,7 @@ class _spam extends \IPS\Dispatcher\Controller
|
||||
|
||||
\IPS\Lang::saveCustom( 'core', "core_question_and_answer_{$id}", $values['qa_question'] );
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=membersettings&controller=spam&tab=qanda' ), 'saved' );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=moderation&controller=spam&tab=qanda' ), 'saved' );
|
||||
}
|
||||
|
||||
/* Display */
|
||||
@@ -354,7 +372,7 @@ class _spam extends \IPS\Dispatcher\Controller
|
||||
\IPS\Lang::deleteCustom( 'core', "core_question_and_answer_{$id}" );
|
||||
|
||||
/* And redirect */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=membersettings&controller=spam&tab=qanda" ) );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=moderation&controller=spam&tab=qanda" ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -367,7 +385,7 @@ class _spam extends \IPS\Dispatcher\Controller
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'spam_service_log' );
|
||||
|
||||
/* Create the table */
|
||||
$table = new \IPS\Helpers\Table\Db( 'core_spam_service_log', \IPS\Http\Url::internal( 'app=core&module=membersettings&controller=spam&do=serviceLogs' ) );
|
||||
$table = new \IPS\Helpers\Table\Db( 'core_spam_service_log', \IPS\Http\Url::internal( 'app=core&module=moderation&controller=spam&do=serviceLogs' ) );
|
||||
|
||||
$table->langPrefix = 'spamlogs_';
|
||||
|
||||
@@ -399,14 +417,14 @@ class _spam extends \IPS\Dispatcher\Controller
|
||||
'settings' => array(
|
||||
'title' => 'prunesettings',
|
||||
'icon' => 'cog',
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=membersettings&controller=spam&do=serviceLogSettings' ),
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=moderation&controller=spam&do=serviceLogSettings' ),
|
||||
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('prunesettings') )
|
||||
),
|
||||
);
|
||||
|
||||
/* Display */
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('spamlogs');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global' )->block( 'spamlogs', $table );
|
||||
\IPS\Output::i()->output = (string) $table;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -426,10 +444,200 @@ class _spam extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$form->saveAsSettings();
|
||||
\IPS\Session::i()->log( 'acplog__spamlog_settings' );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=membersettings&controller=spam&do=serviceLogs' ), 'saved' );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=moderation&controller=spam&do=serviceLogs' ), 'saved' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('spamlogssettings');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('global')->block( 'spamlogssettings', $form, FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Spam defense whitelist
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function whitelist()
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'spam_whitelist_manage' );
|
||||
$table = new \IPS\Helpers\Table\Db( 'core_spam_whitelist', \IPS\Http\Url::internal( 'app=core&module=moderation&controller=spam&do=whitelist' ) );
|
||||
|
||||
$table->filters = array(
|
||||
'spam_whitelist_ip' => 'whitelist_type=\'ip\'',
|
||||
'spam_whitelist_domain' => 'whitelist_type=\'domain\''
|
||||
);
|
||||
|
||||
$table->include = array( 'whitelist_type', 'whitelist_content', 'whitelist_reason', 'whitelist_date' );
|
||||
$table->mainColumn = 'whiteist_content';
|
||||
$table->rowClasses = array( 'whitelist_reason' => array( 'ipsTable_wrap' ) );
|
||||
|
||||
$table->sortBy = $table->sortBy ?: 'whitelist_date';
|
||||
$table->sortDirection = $table->sortDirection ?: 'asc';
|
||||
$table->quickSearch = 'whitelist_content';
|
||||
$table->advancedSearch = array(
|
||||
'whitelist_reason' => \IPS\Helpers\Table\SEARCH_CONTAINS_TEXT,
|
||||
'whitelist_date' => \IPS\Helpers\Table\SEARCH_DATE_RANGE
|
||||
);
|
||||
|
||||
/* Custom parsers */
|
||||
$table->parsers = array(
|
||||
'whitelist_date' => function( $val, $row )
|
||||
{
|
||||
return \IPS\DateTime::ts( $val )->localeDate();
|
||||
},
|
||||
'whitelist_type' => function( $val, $row )
|
||||
{
|
||||
switch( $val )
|
||||
{
|
||||
default:
|
||||
case 'ip':
|
||||
return \IPS\Member::loggedIn()->language()->addToStack('spam_whitelist_ip_select');
|
||||
break;
|
||||
case 'domain':
|
||||
return \IPS\Member::loggedIn()->language()->addToStack('spam_whitelist_domain_select');
|
||||
break;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/* Row buttons */
|
||||
$table->rowButtons = function( $row )
|
||||
{
|
||||
$return = array();
|
||||
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'moderation', 'spam_whitelist_edit' ) )
|
||||
{
|
||||
$return['edit'] = array(
|
||||
'icon' => 'pencil',
|
||||
'title' => 'edit',
|
||||
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('edit') ),
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=moderation&controller=spam&do=whitelistForm&id=' ) . $row['whitelist_id'],
|
||||
);
|
||||
}
|
||||
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'moderation', 'spam_whitelist_delete' ) )
|
||||
{
|
||||
$return['delete'] = array(
|
||||
'icon' => 'times-circle',
|
||||
'title' => 'delete',
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=moderation&controller=spam&do=whitelistDelete&id=' ) . $row['whitelist_id'],
|
||||
'data' => array( 'delete' => '' ),
|
||||
);
|
||||
}
|
||||
|
||||
return $return;
|
||||
};
|
||||
|
||||
/* Add an add button for whitelist */
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'moderation', 'spam_whitelist_add' ) )
|
||||
{
|
||||
\IPS\Output::i()->sidebar['actions'] = array(
|
||||
'add' => array(
|
||||
'primary' => TRUE,
|
||||
'icon' => 'plus',
|
||||
'title' => 'spam_whitelist_add',
|
||||
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('spam_whitelist_add') ),
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=moderation&controller=spam&do=whitelistForm' )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/* Display */
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('spam_whitelist');
|
||||
\IPS\Output::i()->output = (string) $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whitelist add/edit form
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function whitelistForm()
|
||||
{
|
||||
$current = NULL;
|
||||
if ( \IPS\Request::i()->id )
|
||||
{
|
||||
$current = \IPS\Db::i()->select( '*', 'core_spam_whitelist', array( 'whitelist_id=?', \IPS\Request::i()->id ) )->first();
|
||||
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'spam_whitelist_edit' );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'spam_whitelist_add' );
|
||||
}
|
||||
|
||||
/* Build form */
|
||||
$form = new \IPS\Helpers\Form();
|
||||
$form->add( new \IPS\Helpers\Form\Select( 'whitelist_type', $current['whitelist_type'], TRUE,
|
||||
array(
|
||||
'options' => array(
|
||||
'ip' => 'spam_whitelist_ip_select',
|
||||
'domain' => 'spam_whitelist_domain_select'
|
||||
),
|
||||
'toggles' => array(
|
||||
'ip' => array( 'whitelist_ip_content' ),
|
||||
'domain' => array( 'whitelist_domain_content' )
|
||||
)
|
||||
) ) );
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'whitelist_ip_content', $current['whitelist_content'], TRUE, array(), NULL, NULL, NULL, 'whitelist_ip_content' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'whitelist_domain_content', $current['whitelist_content'], TRUE, array( 'placeholder' => 'mycompany.com' ), function( $value ) {
|
||||
if( isset( $value ) AND mb_stripos( $value, '@' ) )
|
||||
{
|
||||
throw new \DomainException( 'whitelist_domain_email_detected' );
|
||||
}
|
||||
}, NULL, NULL, 'whitelist_domain_content' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'whitelist_reason', $current['whitelist_reason'] ) );
|
||||
|
||||
/* Handle submissions */
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$whitelistContent = $values['whitelist_type'] == 'ip' ? $values['whitelist_ip_content'] : $values['whitelist_domain_content'];
|
||||
$save = array(
|
||||
'whitelist_type' => $values['whitelist_type'],
|
||||
'whitelist_content' => $whitelistContent,
|
||||
'whitelist_reason' => $values['whitelist_reason'],
|
||||
'whitelist_date' => time()
|
||||
);
|
||||
|
||||
if ( $current )
|
||||
{
|
||||
unset( $save['whitelist_date'] );
|
||||
\IPS\Db::i()->update( 'core_spam_whitelist', $save, array( 'whitelist_id=?', $current['whitelist_id'] ) );
|
||||
\IPS\Session::i()->log( 'acplog__spam_whitelist_edited', array( 'spam_whitelist_' . $save['whitelist_type'] . '_select' => TRUE, $save['whitelist_content'] => FALSE ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Db::i()->insert( 'core_spam_whitelist', $save );
|
||||
\IPS\Session::i()->log( 'acplog__spam_whitelist_created', array( 'spam_whitelist_' . $save['whitelist_type'] . '_select' => TRUE, $save['whitelist_content'] => FALSE ) );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=moderation&controller=spam&do=whitelist' ), 'saved' );
|
||||
}
|
||||
|
||||
/* Display */
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global' )->block( $current ? $current['whitelist_content'] : 'add', $form, FALSE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete whitelist entry
|
||||
*
|
||||
* return @void
|
||||
*/
|
||||
protected function whitelistDelete()
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'spam_whitelist_delete' );
|
||||
|
||||
/* Make sure the user confirmed the deletion */
|
||||
\IPS\Request::i()->confirmedDelete();
|
||||
|
||||
try
|
||||
{
|
||||
$current = \IPS\Db::i()->select( '*', 'core_spam_whitelist', array( 'whitelist_id=?', \IPS\Request::i()->id ) )->first();
|
||||
\IPS\Session::i()->log( 'acplog__spam_whitelist_deleted', array( 'whitelist_filter_' . $current['whitelist_type'] . '_select' => TRUE, $current['whitelist_content'] => FALSE ) );
|
||||
\IPS\Db::i()->delete( 'core_spam_whitelist', array( 'whitelist_id=?', \IPS\Request::i()->id ) );
|
||||
}
|
||||
catch ( \UnderflowException $e ) { }
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=moderation&controller=spam&do=whitelist' ) );
|
||||
}
|
||||
}
|
||||
+14
-14
@@ -8,7 +8,7 @@
|
||||
* @since 23 Apr 2013
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\admin\membersettings;
|
||||
namespace IPS\core\modules\admin\moderation;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
@@ -51,7 +51,7 @@ class _warnings extends \IPS\Node\Controller
|
||||
$tabs = array();
|
||||
|
||||
/* Reasons */
|
||||
if ( \IPS\Settings::i()->warn_on and \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'membersettings', 'reasons_view' ) )
|
||||
if ( \IPS\Settings::i()->warn_on and \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'moderation', 'reasons_view' ) )
|
||||
{
|
||||
$tabs['reasons'] = 'warn_reasons';
|
||||
if ( $activeTab == 'reasons' )
|
||||
@@ -62,13 +62,13 @@ class _warnings extends \IPS\Node\Controller
|
||||
}
|
||||
|
||||
/* Actions */
|
||||
if ( \IPS\Settings::i()->warn_on and \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'membersettings', 'actions_view' ) )
|
||||
if ( \IPS\Settings::i()->warn_on and \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'moderation', 'actions_view' ) )
|
||||
{
|
||||
$tabs['actions'] = 'warn_actions';
|
||||
if ( $activeTab == 'actions' )
|
||||
{
|
||||
/* Init */
|
||||
$table = new \IPS\Helpers\Table\Db( 'core_members_warn_actions', \IPS\Http\Url::internal( 'app=core&module=membersettings&controller=warnings' ) );
|
||||
$table = new \IPS\Helpers\Table\Db( 'core_members_warn_actions', \IPS\Http\Url::internal( 'app=core&module=moderation&controller=warnings' ) );
|
||||
$table->include = array( 'wa_points', 'wa_mq', 'wa_rpa', 'wa_suspend' );
|
||||
$table->sortBy = $table->sortBy ?: 'wa_points';
|
||||
$table->sortDirection = $table->sortDirection ?: 'asc';
|
||||
@@ -78,21 +78,21 @@ class _warnings extends \IPS\Node\Controller
|
||||
{
|
||||
$return = array();
|
||||
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'membersettings', 'actions_edit' ) )
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'moderation', 'actions_edit' ) )
|
||||
{
|
||||
$return['edit'] = array(
|
||||
'icon' => 'pencil',
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=membersettings&controller=warnings&do=actionForm&id=' ) . $row['wa_id'],
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=moderation&controller=warnings&do=actionForm&id=' ) . $row['wa_id'],
|
||||
'title' => 'edit',
|
||||
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('add') )
|
||||
);
|
||||
}
|
||||
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'membersettings', 'actions_delete' ) )
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'moderation', 'actions_delete' ) )
|
||||
{
|
||||
$return['delete'] = array(
|
||||
'icon' => 'times-circle',
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=membersettings&controller=warnings&do=actionDelete&id=' ) . $row['wa_id'],
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=moderation&controller=warnings&do=actionDelete&id=' ) . $row['wa_id'],
|
||||
'title' => 'delete',
|
||||
'data' => array( 'delete' => '' )
|
||||
);
|
||||
@@ -118,12 +118,12 @@ class _warnings extends \IPS\Node\Controller
|
||||
);
|
||||
|
||||
/* Add button */
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'membersettings', 'actions_add' ) )
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'moderation', 'actions_add' ) )
|
||||
{
|
||||
$table->rootButtons = array(
|
||||
'add' => array(
|
||||
'icon' => 'plus',
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=membersettings&controller=warnings&do=actionForm' ),
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=moderation&controller=warnings&do=actionForm' ),
|
||||
'title' => 'add',
|
||||
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('add') )
|
||||
)
|
||||
@@ -154,7 +154,7 @@ class _warnings extends \IPS\Node\Controller
|
||||
{
|
||||
$form->saveAsSettings();
|
||||
\IPS\Session::i()->log( 'acplog__warn_settings' );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=membersettings&controller=warnings&tab=settings' ), 'saved' );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=moderation&controller=warnings&tab=settings' ), 'saved' );
|
||||
}
|
||||
|
||||
$activeTabContents = (string) $form;
|
||||
@@ -174,7 +174,7 @@ class _warnings extends \IPS\Node\Controller
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global' )->tabs( $tabs, $activeTab, $activeTabContents, \IPS\Http\Url::internal( "app=core&module=membersettings&controller=warnings" ) );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global' )->tabs( $tabs, $activeTab, $activeTabContents, \IPS\Http\Url::internal( "app=core&module=moderation&controller=warnings" ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,7 +241,7 @@ class _warnings extends \IPS\Node\Controller
|
||||
\IPS\Session::i()->log( 'acplog__wa_created', array( $save['wa_points'] => FALSE ) );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=membersettings&controller=warnings&tab=actions' ), 'saved' );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=moderation&controller=warnings&tab=actions' ), 'saved' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'global' )->block( 'warn_action', $form, FALSE );
|
||||
@@ -268,6 +268,6 @@ class _warnings extends \IPS\Node\Controller
|
||||
}
|
||||
catch ( \UnderflowException $e ) { }
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=membersettings&controller=warnings&tab=actions' ), 'saved' );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=moderation&controller=warnings&tab=actions' ), 'saved' );
|
||||
}
|
||||
}
|
||||
@@ -109,15 +109,52 @@ class _dashboard extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Warnings */
|
||||
$warnings = array();
|
||||
|
||||
$dir = @dir( '/' );
|
||||
if ( $dir instanceof \Directory )
|
||||
{
|
||||
$warnings[] = array(
|
||||
'title' => \IPS\Member::loggedIn()->language()->addToStack('open_basedir_title'),
|
||||
'description' => \IPS\Member::loggedIn()->language()->addToStack('open_basedir_desc'),
|
||||
);
|
||||
}
|
||||
|
||||
$functionsToDisable = array( 'exec', 'system', 'passhtru', 'pcntl_exec', 'popen', 'proc_open', 'shell_exec' );
|
||||
$showingFunctionWarning = FALSE;
|
||||
foreach ( $functionsToDisable as $k => $function )
|
||||
{
|
||||
if ( function_exists( $function ) )
|
||||
{
|
||||
$showingFunctionWarning = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
unset( $functionsToDisable[ $k ] );
|
||||
}
|
||||
}
|
||||
if ( $showingFunctionWarning )
|
||||
{
|
||||
$warnings[] = array(
|
||||
'title' => \IPS\Member::loggedIn()->language()->addToStack('disable_functions_title'),
|
||||
'description' => \IPS\Member::loggedIn()->language()->addToStack('disable_functions_desc', FALSE, array( 'sprintf' => array( implode( ', ', $functionsToDisable ) ) ) ),
|
||||
);
|
||||
}
|
||||
|
||||
if ( !\IPS\IN_DEV and ini_get( 'display_errors' ) )
|
||||
{
|
||||
$warnings[] = array(
|
||||
'title' => \IPS\Member::loggedIn()->language()->addToStack('display_errors_title'),
|
||||
'description' => \IPS\Member::loggedIn()->language()->addToStack('display_errors_desc'),
|
||||
'risk' => "medium",
|
||||
);
|
||||
}
|
||||
|
||||
$tasks = \IPS\Db::i()->select( '*', 'core_tasks', 'lock_count >= 3' );
|
||||
|
||||
$keys = array();
|
||||
foreach( $tasks as $task )
|
||||
{
|
||||
$keys[] = $task['key'];
|
||||
}
|
||||
|
||||
if ( !empty( $keys ) )
|
||||
{
|
||||
$warnings[] = array(
|
||||
@@ -143,6 +180,50 @@ class _dashboard extends \IPS\Dispatcher\Controller
|
||||
);
|
||||
}
|
||||
|
||||
if( !\IPS\Settings::i()->orig_tables_checked )
|
||||
{
|
||||
/* Check if we have any orig_* tables */
|
||||
$tables = \IPS\Db::i()->getTables( 'orig_' . \IPS\Db::i()->prefix );
|
||||
|
||||
/* If we don't have any, we're good. Set a flag so we don't check this every dashboard load. */
|
||||
if( !count( $tables ) )
|
||||
{
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => 1 ), array( 'conf_key=?', 'orig_tables_checked' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Determine if the background queue task has already been launched */
|
||||
try
|
||||
{
|
||||
\IPS\Db::i()->select( '*', 'core_queue', array( "`key`=?", 'CleanupOrigTables' ) )->first();
|
||||
$inProgress = TRUE;
|
||||
}
|
||||
catch( \UnderflowException $e )
|
||||
{
|
||||
$inProgress = FALSE;
|
||||
}
|
||||
|
||||
/* Launch the task if we clicked to do so */
|
||||
if( !$inProgress AND isset( \IPS\Request::i()->cleanupOrigTables ) AND \IPS\Request::i()->cleanupOrigTables )
|
||||
{
|
||||
\IPS\Task::queue( 'core', 'CleanupOrigTables', array( 'originalCount' => count( $tables ) ), 5 );
|
||||
|
||||
$inProgress = TRUE;
|
||||
|
||||
\IPS\Output::i()->inlineMessage = \IPS\Member::loggedIn()->language()->addToStack('orig_tables_rebuilding');
|
||||
}
|
||||
|
||||
if( !$inProgress )
|
||||
{
|
||||
$warnings[] = array(
|
||||
'title' => \IPS\Member::loggedIn()->language()->addToStack('block_core_OrigTables'),
|
||||
'description' => \IPS\Member::loggedIn()->language()->addToStack('orig_cleanup_suggested')
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check Tasks */
|
||||
try
|
||||
{
|
||||
@@ -155,21 +236,21 @@ class _dashboard extends \IPS\Dispatcher\Controller
|
||||
if( \IPS\Settings::i()->task_use_cron == 'cron' )
|
||||
{
|
||||
$warnings[] = array(
|
||||
'title' => \IPS\Member::loggedIn()->language()->addToStack( 'dashboard_tasks_broken' ),
|
||||
'description' => \IPS\Member::loggedIn()->language()->addToStack( 'dashboard_tasks_cron_broken_desc' )
|
||||
'title' => \IPS\Member::loggedIn()->language()->addToStack( 'dashboard_tasksrun_broken' ),
|
||||
'description' => \IPS\Member::loggedIn()->language()->addToStack( \IPS\CIC ? 'dashboard_tasks_cron_broken_desc_cic' : 'dashboard_tasks_cron_broken_desc' )
|
||||
);
|
||||
}
|
||||
elseif( \IPS\Settings::i()->task_use_cron == 'web' )
|
||||
{
|
||||
$warnings[] = array(
|
||||
'title' => \IPS\Member::loggedIn()->language()->addToStack( 'dashboard_tasks_broken' ),
|
||||
'title' => \IPS\Member::loggedIn()->language()->addToStack( 'dashboard_tasksrun_broken' ),
|
||||
'description' => \IPS\Member::loggedIn()->language()->addToStack( 'dashboard_tasks_web_broken_desc' )
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$warnings[] = array(
|
||||
'title' => \IPS\Member::loggedIn()->language()->addToStack( 'dashboard_tasks_broken' ),
|
||||
'title' => \IPS\Member::loggedIn()->language()->addToStack( 'dashboard_tasksrun_broken' ),
|
||||
'description' => \IPS\Member::loggedIn()->language()->addToStack( 'dashboard_tasks_not_enough_desc' )
|
||||
);
|
||||
}
|
||||
@@ -184,8 +265,10 @@ class _dashboard extends \IPS\Dispatcher\Controller
|
||||
'description' => \IPS\Member::loggedIn()->language()->addToStack('dasbhoard_tasks_site_offline_desc')
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* If there have been more than 10 datastore failurs in the last hour, or if an instant test fails, show a message */
|
||||
/* If there have been more than 10 datastore failures in the last hour, or if an instant test fails, show a message */
|
||||
if( !\IPS\Data\Store::i()->test() OR \IPS\Db::i()->select( 'COUNT(*)', 'core_log', array( '`category`=? AND `time`>?', 'datastore', \IPS\DateTime::create()->sub( new \DateInterval( 'PT1H' ) )->getTimestamp() ) )->first() >= 10 )
|
||||
{
|
||||
/* Have we just recently updated the configuration? If so, ignore this warning for 24 hours */
|
||||
@@ -197,13 +280,92 @@ class _dashboard extends \IPS\Dispatcher\Controller
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ( \IPS\CIC )
|
||||
{
|
||||
try
|
||||
{
|
||||
$cicEmails = \IPS\Data\Cache::i()->getWithExpire( 'cicEmailUsage', TRUE );
|
||||
}
|
||||
catch( \OutOfRangeException $e )
|
||||
{
|
||||
preg_match( '/^\/var\/www\/html\/(.+?)(?:\/|$)/i', \IPS\ROOT_PATH, $matches );
|
||||
|
||||
try
|
||||
{
|
||||
$cicEmails = \IPS\Http\Url::external( "http://ips-cic-email.invisioncic.com/blocked.php?account={$matches[1]}" )->request()->get()->decodeJson();
|
||||
}
|
||||
catch( \Exception $e )
|
||||
{
|
||||
/* Request failed, so assume okay and try again in an hour */
|
||||
$cicEmails = array( 'status' => 'OKAY', 'time' => time() );
|
||||
}
|
||||
|
||||
\IPS\Data\Cache::i()->storeWithExpire( 'cicEmailUsage', $cicEmails, \IPS\DateTime::create()->add( new \DateInterval( 'PT1H' ) ), true );
|
||||
}
|
||||
|
||||
if ( isset( $cicEmails['status'] ) AND $cicEmails['status'] == 'BLOCKED' )
|
||||
{
|
||||
$warnings[] = array(
|
||||
'title' => \IPS\Member::loggedIn()->language()->addToStack( 'dashboard_cic_email_quota' ),
|
||||
'description' => \IPS\Member::loggedIn()->language()->addToStack( 'dashboard_cic_email_quota_desc' )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/* Cache Check */
|
||||
if ( \IPS\CACHE_METHOD AND \IPS\CACHE_METHOD != 'None' AND \IPS\Data\Cache::i() instanceof \IPS\Data\Cache\None )
|
||||
{
|
||||
$warnings[] = array(
|
||||
'title' => \IPS\Member::loggedIn()->language()->addToStack( 'dashboard_invalid_cachesetup' ),
|
||||
'description' => \IPS\Member::loggedIn()->language()->addToStack( 'dashboard_invalid_cachesetup_desc' )
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/* Get new core update available data */
|
||||
$update = \IPS\Application::load( 'core' )->availableUpgrade( TRUE );
|
||||
$update = \IPS\Application::load( 'core' )->availableUpgrade( TRUE );
|
||||
|
||||
/* Determine if there are any new features to show */
|
||||
$latestFeatureId = \IPS\Application::load( 'core' )->newFeature();
|
||||
$features = array();
|
||||
|
||||
try
|
||||
{
|
||||
$latestSeenFeature = \IPS\Db::i()->select( 'feature_id', 'core_members_feature_seen', array( 'member_id=?', \IPS\Member::loggedIn()->member_id ) )->first();
|
||||
}
|
||||
catch( \UnderflowException $e )
|
||||
{
|
||||
$latestSeenFeature = 0;
|
||||
}
|
||||
|
||||
if( $latestFeatureId AND ( !$latestSeenFeature OR $latestSeenFeature < $latestFeatureId ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$features = json_encode( \IPS\Http\Url::ips('newFeatures')->setQueryString( array( 'since' => (int) $latestSeenFeature ) )->request()->get()->decodeJson() );
|
||||
|
||||
/* Reset our last feature ID information so this doesn't show on subsequent page loads */
|
||||
\IPS\Db::i()->replace( 'core_members_feature_seen', array( 'member_id' => \IPS\Member::loggedIn()->member_id, 'feature_id' => $latestFeatureId ) );
|
||||
}
|
||||
catch( \RuntimeException $e ){}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('dashboard');
|
||||
\IPS\Output::i()->customHeader = \IPS\Theme::i()->getTemplate( 'dashboard' )->dashboardHeader( $info, $blocks );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'dashboard' )->dashboard( $update, $toShow, $blocks, $info, $bulletins, $warnings );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'dashboard' )->dashboard( $update, $features, $toShow, $blocks, $info, $bulletins, $warnings );
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the latest features we've seen so that we can see them again
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function whatsNew()
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_members_feature_seen', array( 'member_id=?', \IPS\Member::loggedIn()->member_id ) );
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=overview&controller=dashboard" ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -234,9 +396,12 @@ class _dashboard extends \IPS\Dispatcher\Controller
|
||||
|
||||
$blocks[ \IPS\Member::loggedIn()->member_id ] = $toShow;
|
||||
|
||||
\IPS\Settings::i()->acp_dashboard_blocks = json_encode( $blocks );
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => \IPS\Settings::i()->acp_dashboard_blocks ), array( 'conf_key=?', 'acp_dashboard_blocks' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
\IPS\Settings::i()->changeValues( array( 'acp_dashboard_blocks' => json_encode( $blocks ) ) );
|
||||
}
|
||||
/* Upon initial upgrade to 4.3 the key won't exist, so apply to bg queue by default */
|
||||
elseif( !array_key_exists( 'collapsed', $toShow ) )
|
||||
{
|
||||
$toShow['collapsed'] = array( 'core_BackgroundQueue' );
|
||||
}
|
||||
|
||||
if( $return === TRUE )
|
||||
@@ -292,20 +457,17 @@ class _dashboard extends \IPS\Dispatcher\Controller
|
||||
|
||||
$saveBlocks = \IPS\Request::i()->blocks;
|
||||
|
||||
if( !isset( $saveBlocks['main'] ) )
|
||||
foreach( array( 'main', 'side', 'collapsed' ) as $saveKey )
|
||||
{
|
||||
$saveBlocks['main'] = array();
|
||||
}
|
||||
if( !isset( $saveBlocks['side'] ) )
|
||||
{
|
||||
$saveBlocks['side'] = array();
|
||||
if( !isset( $saveBlocks[ $saveKey ] ) )
|
||||
{
|
||||
$saveBlocks[ $saveKey ] = array();
|
||||
}
|
||||
}
|
||||
|
||||
$blocks[ \IPS\Member::loggedIn()->member_id ] = $saveBlocks;
|
||||
|
||||
\IPS\Settings::i()->acp_dashboard_blocks = json_encode( $blocks );
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => \IPS\Settings::i()->acp_dashboard_blocks ), array( 'conf_key=?', 'acp_dashboard_blocks' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
\IPS\Settings::i()->changeValues( array( 'acp_dashboard_blocks' => json_encode( $blocks ) ) );
|
||||
|
||||
if( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
|
||||
@@ -72,16 +72,21 @@ class _files extends \IPS\Dispatcher\Controller
|
||||
}*/
|
||||
|
||||
$table = new \IPS\Helpers\Table\Db( 'core_attachments', \IPS\Http\Url::internal( 'app=core&module=overview&controller=files' ) );
|
||||
$table->tableTemplate = array( \IPS\Theme::i()->getTemplate( 'dashboard' ), 'fileTable' );
|
||||
$table->rowsTemplate = array( \IPS\Theme::i()->getTemplate( 'dashboard' ), 'fileTableRows' );
|
||||
$table->filters = array(
|
||||
'images' => "attach_is_image=1",
|
||||
'files' => "attach_is_image=0",
|
||||
);
|
||||
$table->include = array( 'attach_file', 'attach_filesize', 'attach_date', 'attach_member_id' );
|
||||
|
||||
$table->include = array( 'attach_id', 'attach_file', 'attach_filesize', 'attach_date', 'attach_member_id' );
|
||||
$table->rowClasses = array( 'attach_file' => array( 'ipsTable_wrap' ) );
|
||||
|
||||
if ( $table->filter !== 'images' )
|
||||
{
|
||||
$table->include[] = 'attach_hits';
|
||||
}
|
||||
$table->noSort = array( 'attach_type' );
|
||||
$table->noSort = array( 'attach_type', 'attach_id' );
|
||||
$table->quickSearch = 'attach_file';
|
||||
$table->parsers = array(
|
||||
'attach_file' => function( $val, $row ) use ( $table )
|
||||
@@ -94,7 +99,7 @@ class _files extends \IPS\Dispatcher\Controller
|
||||
else
|
||||
{
|
||||
$url = \IPS\Http\Url::external( \IPS\Settings::i()->base_url . "applications/core/interface/file/attachment.php" )->setQueryString( 'id', $row['attach_id'] )->makeSafeForAcp( FALSE );
|
||||
$val = htmlentities( $val, \IPS\HTMLENTITIES, 'UTF-8', FALSE );
|
||||
$val = htmlentities( $val, ENT_DISALLOWED, 'UTF-8', FALSE );
|
||||
return "<a href='{$url}' target='_blank'>{$val}</a>";
|
||||
}
|
||||
},
|
||||
@@ -133,7 +138,7 @@ class _files extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
else
|
||||
{
|
||||
return "<a href='" . \IPS\Http\Url::internal( 'app=core&module=members&controller=members&do=edit&id=' . $val ) . "'>" . htmlentities( \IPS\Member::load( $val )->name, \IPS\HTMLENTITIES, 'UTF-8', FALSE ) . '</a>';
|
||||
return "<a href='" . \IPS\Http\Url::internal( 'app=core&module=members&controller=members&do=edit&id=' . $val ) . "'>" . htmlentities( \IPS\Member::load( $val )->name, ENT_DISALLOWED, 'UTF-8', FALSE ) . '</a>';
|
||||
|
||||
}
|
||||
}
|
||||
@@ -168,7 +173,9 @@ class _files extends \IPS\Dispatcher\Controller
|
||||
|
||||
return $buttons;
|
||||
};
|
||||
|
||||
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'dashboard/files.css', 'core', 'admin' ) );
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'admin_files.js', 'core', 'admin' ) );
|
||||
\IPS\Output::i()->output = (string) $table;
|
||||
}
|
||||
|
||||
@@ -393,8 +400,7 @@ class _files extends \IPS\Dispatcher\Controller
|
||||
\IPS\Task::queue( 'core', 'DeleteMovedFiles', array( 'delete' => true ), 5, array( 'delete' ) ); /* We use a key in the data array just to trigger the code that deletes duplicate tasks */
|
||||
}
|
||||
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => json_encode( $values ) ), array( 'conf_key=?', 'upload_settings' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
\IPS\Settings::i()->changeValues( array( 'upload_settings' => json_encode( $values ) ) );
|
||||
|
||||
/* Clear guest page caches */
|
||||
\IPS\Data\Cache::i()->clearAll();
|
||||
@@ -558,7 +564,7 @@ class _files extends \IPS\Dispatcher\Controller
|
||||
$toggles = array();
|
||||
foreach ( new \DirectoryIterator( \IPS\ROOT_PATH . '/system/File' ) as $f )
|
||||
{
|
||||
if ( !$f->isDot() and mb_substr( $f, -4 ) === '.php' and $f != 'File.php' and $f != 'Iterator.php' )
|
||||
if ( !$f->isDot() and mb_substr( $f, -4 ) === '.php' and $f != 'File.php' and $f != 'Iterator.php' and $f != 'Exception.php' )
|
||||
{
|
||||
$key = mb_substr( $f, 0, -4 );
|
||||
|
||||
@@ -566,6 +572,12 @@ class _files extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Hide FTP option from form unless it's already in use */
|
||||
if ( ( $key === 'Ftp' AND isset( $current['method'] ) AND $current['method'] !== 'Ftp' ) OR ( $key === 'Ftp' AND !isset( $current['method'] ) ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$handlers[ $key ] = 'filehandler__' . $key;
|
||||
|
||||
@@ -713,8 +725,7 @@ class _files extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => json_encode( $settings ) ), array( 'conf_key=?', 'upload_settings' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
\IPS\Settings::i()->changeValues( array( 'upload_settings' => json_encode( $settings ) ) );
|
||||
|
||||
if ( $values['filestorage_move'] )
|
||||
{
|
||||
@@ -853,4 +864,37 @@ class _files extends \IPS\Dispatcher\Controller
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=overview&controller=files" ), 'orphaned_files_tasks_added' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Multimod
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function multimod()
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'files_delete' );
|
||||
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
if( !isset( \IPS\Request::i()->multimod ) OR !is_array( \IPS\Request::i()->multimod ) OR !count( \IPS\Request::i()->multimod ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'nothing_mm_selected', '2C158/6', 403, '' );
|
||||
}
|
||||
|
||||
foreach ( \IPS\Db::i()->select( '*', 'core_attachments', \IPS\Db::i()->in( 'attach_id', array_keys( \IPS\Request::i()->multimod ) ) ) as $attachment )
|
||||
{
|
||||
\IPS\File::get( 'core_Attachment', $attachment['attach_location'] )->delete();
|
||||
|
||||
if( $attachment['attach_thumb_location'] )
|
||||
{
|
||||
\IPS\File::get( 'core_Attachment', $attachment['attach_thumb_location'] )->delete();
|
||||
}
|
||||
|
||||
\IPS\Session::i()->log( 'acplogs__file_deleted', array( $attachment['attach_file'] => FALSE ) );
|
||||
}
|
||||
|
||||
\IPS\Db::i()->delete( 'core_attachments', \IPS\Db::i()->in( 'attach_id', array_keys( \IPS\Request::i()->multimod ) ) );
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=overview&controller=files" ), 'deleted' );
|
||||
}
|
||||
}
|
||||
@@ -1,403 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Security Settings
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 11 Jun 2013
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\admin\overview;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Security Settings
|
||||
*/
|
||||
class _security extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'security_manage' );
|
||||
parent::execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Security Center
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
{
|
||||
/* Init */
|
||||
$content = array();
|
||||
|
||||
\IPS\Output::i()->sidebar['actions'] = array(
|
||||
'settings' => array(
|
||||
'icon' => 'cog',
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=overview&controller=security&do=settings' ),
|
||||
'title' => 'security_settings',
|
||||
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('security_settings') )
|
||||
),
|
||||
'list_admins' => array(
|
||||
'icon' => 'key',
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=members&controller=members&filter=members_filter_administrators' ),
|
||||
'title' => 'security_list_admins',
|
||||
),
|
||||
);
|
||||
|
||||
/* open_basedir */
|
||||
$dir = @dir( '/' );
|
||||
if ( $dir instanceof Directory )
|
||||
{
|
||||
$content[] = array(
|
||||
'title' => \IPS\Member::loggedIn()->language()->addToStack('open_basedir_title'),
|
||||
'description' => \IPS\Member::loggedIn()->language()->addToStack('open_basedir_desc'),
|
||||
'risk' => "high",
|
||||
);
|
||||
}
|
||||
|
||||
/* Htaccess Protection */
|
||||
$needUploads = FALSE;
|
||||
foreach( \IPS\Db::i()->select( '*', 'core_file_storage', array( 'method=?', 'FileSystem' ) ) as $uploads )
|
||||
{
|
||||
$uploads = json_decode( $uploads['configuration'], TRUE );
|
||||
|
||||
if( isset( $uploads['dir'] ) )
|
||||
{
|
||||
$uploads['dir'] = str_replace( '{root}', \IPS\ROOT_PATH, $uploads['dir'] );
|
||||
|
||||
if( !is_file( $uploads['dir'] . '/.htaccess' ) )
|
||||
{
|
||||
$needUploads = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$storeSettings = json_decode( \IPS\STORE_CONFIG, TRUE );
|
||||
if ( ( $needUploads OR
|
||||
( \IPS\STORE_METHOD == 'FileSystem' AND !is_file( str_replace( '{root}', \IPS\ROOT_PATH, $storeSettings['path'] ) . '/.htaccess' ) ) ) AND !\IPS\NO_WRITES )
|
||||
{
|
||||
$content[] = array(
|
||||
'title' => \IPS\Member::loggedIn()->language()->addToStack('htaccess_title'),
|
||||
'description' => \IPS\Member::loggedIn()->language()->addToStack('htaccess_desc'),
|
||||
'risk' => "high",
|
||||
'button' => array( 'title' => \IPS\Member::loggedIn()->language()->addToStack('security_run_tool'), 'action' => "app=core&module=overview&controller=security&do=htaccess" ),
|
||||
);
|
||||
}
|
||||
|
||||
/* Configuration File */
|
||||
if ( is_writable( \IPS\ROOT_PATH . '/conf_global.php' ) AND !\IPS\NO_WRITES )
|
||||
{
|
||||
$content[] = array(
|
||||
'title' => \IPS\Member::loggedIn()->language()->addToStack('conf_writeable_title'),
|
||||
'description' => \IPS\Member::loggedIn()->language()->addToStack('conf_writeable_desc'),
|
||||
'risk' => "high",
|
||||
'button' => array( 'title' => \IPS\Member::loggedIn()->language()->addToStack('security_run_tool'), 'action' => "app=core&module=overview&controller=security&do=conf" ),
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/* Disabled PHP Functions */
|
||||
$functionsToDisable = array( 'exec', 'system', 'passhtru', 'pcntl_exec', 'popen', 'proc_open', 'shell_exec' );
|
||||
$showingFunctionWarning = FALSE;
|
||||
|
||||
foreach ( $functionsToDisable as $k => $function )
|
||||
{
|
||||
if ( function_exists( $function ) )
|
||||
{
|
||||
$showingFunctionWarning = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
unset( $functionsToDisable[ $k ] );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $showingFunctionWarning )
|
||||
{
|
||||
$content[] = array(
|
||||
'title' => \IPS\Member::loggedIn()->language()->addToStack('disable_functions_title'),
|
||||
'description' => \IPS\Member::loggedIn()->language()->addToStack('disable_functions_desc', FALSE, array( 'sprintf' => array( implode( ', ', $functionsToDisable ) ) ) ),
|
||||
'risk' => "high",
|
||||
);
|
||||
}
|
||||
|
||||
/* Display Errors */
|
||||
if ( ini_get( 'display_errors' ) )
|
||||
{
|
||||
$content[] = array(
|
||||
'title' => \IPS\Member::loggedIn()->language()->addToStack('display_errors_title'),
|
||||
'description' => \IPS\Member::loggedIn()->language()->addToStack('display_errors_desc'),
|
||||
'risk' => "medium",
|
||||
);
|
||||
}
|
||||
|
||||
/* ACP Directory Name */
|
||||
if ( \IPS\CP_DIRECTORY == 'admin' and !\IPS\CIC )
|
||||
{
|
||||
$content[] = array(
|
||||
'title' => \IPS\Member::loggedIn()->language()->addToStack('rename_admin_title'),
|
||||
'description' => \IPS\Member::loggedIn()->language()->addToStack('rename_admin_desc'),
|
||||
'risk' => "low",
|
||||
'button' => array( 'title' => \IPS\Member::loggedIn()->language()->addToStack('security_learn_more'), 'action' => "app=core&module=overview&controller=security&do=renameAdmin" ),
|
||||
);
|
||||
}
|
||||
|
||||
/* ACP Password Protection */
|
||||
if ( ! is_file( \IPS\ROOT_PATH . '/' . \IPS\CP_DIRECTORY . '/.htaccess' ) AND !\IPS\NO_WRITES AND !\IPS\CIC )
|
||||
{
|
||||
$content[] = array(
|
||||
'title' => \IPS\Member::loggedIn()->language()->addToStack('admin_pass_title'),
|
||||
'description' => \IPS\Member::loggedIn()->language()->addToStack('admin_pass_desc'),
|
||||
'risk' => "low",
|
||||
'button' => array( 'title' => \IPS\Member::loggedIn()->language()->addToStack('security_run_tool'), 'action' => "app=core&module=overview&controller=security&do=acpHtaccess" ),
|
||||
);
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('security_center');
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'system/security.css', 'core', 'admin' ) );
|
||||
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'overview' )->security( $content );
|
||||
}
|
||||
|
||||
/**
|
||||
* Security Settings
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function settings()
|
||||
{
|
||||
$form = new \IPS\Helpers\Form;
|
||||
|
||||
/* IP Addresses */
|
||||
$form->addHeader( 'security_header_ips' );
|
||||
if ( !\IPS\CIC )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'xforward_matching', \IPS\Settings::i()->xforward_matching, FALSE ) );
|
||||
}
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'match_ipaddress', \IPS\Settings::i()->match_ipaddress, FALSE ) );
|
||||
if( \IPS\BYPASS_ACP_IP_CHECK === TRUE )
|
||||
{
|
||||
\IPS\Member::loggedIn()->language()->words['match_ipaddress_warning'] = \IPS\Member::loggedIn()->language()->addToStack('ip_override_warn');
|
||||
}
|
||||
|
||||
/* Account Security */
|
||||
$form->addHeader( 'security_header_accounts' );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'device_management', \IPS\Settings::i()->device_management, FALSE ) );
|
||||
|
||||
/* Password Strength */
|
||||
$form->addHeader( 'security_header_passwords' );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'password_strength_meter', \IPS\Settings::i()->password_strength_meter, FALSE, array( 'togglesOn' => array( 'password_strength_meter_enforce' ) ), NULL, NULL, NULL, 'password_strength_meter' ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'password_strength_meter_enforce', \IPS\Settings::i()->password_strength_meter_enforce, FALSE, array( 'togglesOn' => array( 'password_strength_option' ) ), NULL, NULL, NULL, 'password_strength_meter_enforce' ) );
|
||||
$strengthOptions = array(
|
||||
'3' => 'strength_3',
|
||||
'4' => 'strength_4',
|
||||
'5' => 'strength_5',
|
||||
);
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'password_strength_option', \IPS\Settings::i()->password_strength_option, FALSE, array( 'options' => $strengthOptions ), NULL, NULL, NULL, 'password_strength_option' ) );
|
||||
|
||||
/* ACP Link */
|
||||
$form->addHeader( 'security_header_admincp' );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'security_remove_acp_link', !\IPS\Settings::i()->security_remove_acp_link, FALSE ) );
|
||||
|
||||
/* Handle Submissions */
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$values['security_remove_acp_link'] = $values['security_remove_acp_link'] ? FALSE : TRUE;
|
||||
|
||||
/* Disabling the password strength meter should also disable enforcing a strength */
|
||||
$values['password_strength_meter_enforce'] = $values['password_strength_meter'] ? $values['password_strength_meter_enforce'] : FALSE;
|
||||
|
||||
$form->saveAsSettings( $values );
|
||||
|
||||
\IPS\Session::i()->log( 'acplogs__security_settings' );
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=overview&controller=security" ), 'saved' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('security_settings');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('global')->block( 'storage_settings', $form );
|
||||
}
|
||||
|
||||
/**
|
||||
* Change conf global permissions
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function conf()
|
||||
{
|
||||
/* INIT */
|
||||
$done = FALSE;
|
||||
|
||||
/* Try... */
|
||||
if ( \IPS\NO_WRITES or !@chmod( \IPS\ROOT_PATH . '/conf_global.php', 0444 ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'conf_not_altered', '2C258/2', 500, '' );
|
||||
}
|
||||
|
||||
/* All Done */
|
||||
\IPS\Session::i()->log( 'acplogs__security_conf' );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=overview&controller=security" ), 'conf_altered' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add htaccess files to writeable directory
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function htaccess()
|
||||
{
|
||||
if ( \IPS\NO_WRITES )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_writes', '1C258/7', 403, '' );
|
||||
}
|
||||
|
||||
/* INIT */
|
||||
$errors = array();
|
||||
$deny = <<<EOF
|
||||
#<ipb-protection>
|
||||
<Files ~ "^.*\.(php|cgi|pl|php3|php4|php5|php6|phtml|shtml|([a-z0-9]{32}))$">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
#</ipb-protection>
|
||||
EOF;
|
||||
|
||||
foreach( \IPS\Db::i()->select( '*', 'core_file_storage', array( 'method=?', 'FileSystem' ) ) as $uploads )
|
||||
{
|
||||
$uploads = json_decode( $uploads['configuration'], TRUE );
|
||||
|
||||
if( isset( $uploads['dir'] ) )
|
||||
{
|
||||
$uploads['dir'] = str_replace( '{root}', \IPS\ROOT_PATH, $uploads['dir'] );
|
||||
|
||||
if( !is_file( $uploads['dir'] . '/.htaccess' ) )
|
||||
{
|
||||
if ( !@\file_put_contents( $uploads['dir'] . '/.htaccess', $deny ) )
|
||||
{
|
||||
$errors[] = $uploads['dir'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $uploadSettings['FileSystem']['dir'] ) )
|
||||
{
|
||||
$directory = $uploadSettings['FileSystem']['dir'];
|
||||
|
||||
if ( !@\file_put_contents( $directory . '/.htaccess', $deny ) )
|
||||
{
|
||||
$errors[] = $directory;
|
||||
}
|
||||
}
|
||||
|
||||
$storeSettings = json_decode( \IPS\STORE_CONFIG, TRUE );
|
||||
if ( \IPS\STORE_METHOD == 'FileSystem' )
|
||||
{
|
||||
$directory = str_replace( '{root}', \IPS\ROOT_PATH, $storeSettings['path'] );
|
||||
|
||||
if ( !@\file_put_contents( $directory . '/.htaccess', $deny ) )
|
||||
{
|
||||
$errors[] = $directory;
|
||||
}
|
||||
}
|
||||
|
||||
if( count( $errors ) )
|
||||
{
|
||||
\IPS\Output::i()->error( \IPS\Member::loggedIn()->language()->addToStack( 'htaccess_not_written', FALSE, array( 'sprintf' => \IPS\Member::loggedIn()->language()->formatList( $errors ) ) ), '2C258/1', 403, '', array(), $deny );
|
||||
}
|
||||
|
||||
/* All Done */
|
||||
\IPS\Session::i()->log( 'acplogs__security_htaccess_writeable' );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=overview&controller=security" ), 'htaccess_written' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename ACP directory
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function renameAdmin()
|
||||
{
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('rename_admin_title');
|
||||
\IPS\Output::i()->breadcrumb[] = array( NULL, \IPS\Output::i()->title );
|
||||
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'overview' )->securityRenameAdmin();
|
||||
}
|
||||
|
||||
/**
|
||||
* ACP Htaccess Protection
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function acpHtaccess()
|
||||
{
|
||||
if ( \IPS\NO_WRITES )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_writes', '1C258/6', 403, '' );
|
||||
}
|
||||
|
||||
if ( !is_writable( \IPS\ROOT_PATH . '/' . \IPS\CP_DIRECTORY ) )
|
||||
{
|
||||
\IPS\Output::i()->error( \IPS\Member::loggedIn()->language()->addToStack( 'err_not_writable', FALSE, array( 'sprintf' => array( \IPS\ROOT_PATH . '/' . \IPS\CP_DIRECTORY ) ) ), '1C258/5', 403, '' );
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'htaccess_username', NULL, TRUE ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'htaccess_password', NULL, TRUE ) );
|
||||
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$done = FALSE;
|
||||
/* See this for an explanation why ErrorDocument is needed: http://www.myriadinteractive.com/blog/view/id/29/conflict-between-apache-url-rewriting-and-basic-authentication */
|
||||
$htaccess_auth = "ErrorDocument 401 \"Unauthorized Access\"\n"
|
||||
. "AuthType Basic\n"
|
||||
. "AuthName \"Invision Community AdminCP\"\n"
|
||||
. 'AuthUserFile "' . \IPS\ROOT_PATH . '/' . \IPS\CP_DIRECTORY . "/.htpasswd\"\n"
|
||||
. "Require valid-user\n";
|
||||
|
||||
$htaccess_pw = $values['htaccess_username'] . ":" .
|
||||
( ( mb_strtoupper( mb_substr( PHP_OS, 0, 3 ) ) === 'WIN' ) ? $values['htaccess_password'] : crypt( $values['htaccess_password'], base64_encode( $values['htaccess_password'] ) ) );
|
||||
|
||||
if ( $FH = @\fopen( \IPS\ROOT_PATH . '/' . \IPS\CP_DIRECTORY . '/.htpasswd', 'w' ) )
|
||||
{
|
||||
\fwrite( $FH, $htaccess_pw );
|
||||
\fclose( $FH );
|
||||
|
||||
$FF = @\fopen( \IPS\ROOT_PATH . '/' . \IPS\CP_DIRECTORY . '/.htaccess', 'w' );
|
||||
\fwrite( $FF, $htaccess_auth );
|
||||
\fclose( $FF );
|
||||
|
||||
$done = TRUE;
|
||||
|
||||
\IPS\Session::i()->log( 'acplogs__security_acp_password' );
|
||||
\IPS\IPS::resyncIPSCloud('Added htaccess protection to ACP');
|
||||
}
|
||||
|
||||
/* All Done */
|
||||
if ( $done )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=overview&controller=security" ), 'admin_pass_written' );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->error( 'admin_pass_not_written', '1C258/3', 403, '' );
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->message( 'admin_pass_warning', 'warning' );
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('admin_pass_title');
|
||||
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'global' )->block( \IPS\Output::i()->title, $form );
|
||||
}
|
||||
}
|
||||
@@ -190,6 +190,7 @@ class _advertisements extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->add( new \IPS\Helpers\Form\Select( 'ads_circulation', \IPS\Settings::i()->ads_circulation, TRUE, array( 'options' => array( 'random' => 'ad_circ_random', 'newest' => 'ad_circ_newest', 'oldest' => 'ad_circ_oldest', 'least' => 'ad_circ_leasti' ) ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'ads_force_sidebar', \IPS\Settings::i()->ads_force_sidebar, TRUE ) );
|
||||
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
@@ -268,8 +269,7 @@ class _advertisements extends \IPS\Dispatcher\Controller
|
||||
$adsExist = (bool) \IPS\Db::i()->select( 'COUNT(*)', 'core_advertisements', 'ad_active=1' )->first();
|
||||
if ( $adsExist != \IPS\Settings::i()->ads_exist )
|
||||
{
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => $adsExist ), array( 'conf_key=?', 'ads_exist' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
\IPS\Settings::i()->changeValues( array( 'ads_exist' => $adsExist ) );
|
||||
}
|
||||
|
||||
/* Clear guest page caches */
|
||||
@@ -537,8 +537,7 @@ class _advertisements extends \IPS\Dispatcher\Controller
|
||||
$adsExist = (bool) \IPS\Db::i()->select( 'COUNT(*)', 'core_advertisements', 'ad_active=1' )->first();
|
||||
if ( $adsExist != \IPS\Settings::i()->ads_exist )
|
||||
{
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => $adsExist ), array( 'conf_key=?', 'ads_exist' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
\IPS\Settings::i()->changeValues( array( 'ads_exist' => $adsExist ) );
|
||||
}
|
||||
|
||||
/* Clear guest page caches */
|
||||
|
||||
@@ -50,7 +50,7 @@ class _promote extends \IPS\Dispatcher\Controller
|
||||
protected function manage()
|
||||
{
|
||||
/* Work out output */
|
||||
$activeTabContents = call_user_func( array( $this, '_manage' . ucfirst( $this->activeTab ) ) );
|
||||
$activeTabContents = call_user_func( array( $this, '_manage' . mb_ucfirst( $this->activeTab ) ) );
|
||||
|
||||
/* If this is an AJAX request, just return it */
|
||||
if( \IPS\Request::i()->isAjax() )
|
||||
@@ -232,11 +232,11 @@ class _promote extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function _manageTwitter()
|
||||
{
|
||||
$twitter = \IPS\Login::getHandler('Twitter');
|
||||
$twitter = \IPS\Login\Handler::findMethod('IPS\Login\Handler\Oauth1\Twitter');
|
||||
$account = \IPS\core\Promote::getPromoter('Twitter')->setMember( \IPS\Member::loggedIn() );
|
||||
|
||||
/* Have we set up Facebook yet? */
|
||||
if ( ! $twitter->settings['consumer_key'] )
|
||||
|
||||
/* Have we set up Twitter yet? */
|
||||
if ( !$twitter OR !$twitter->settings['consumer_key'] )
|
||||
{
|
||||
/* Nope, so lets do that first... */
|
||||
return \IPS\Theme::i()->getTemplate( 'promote' )->warningNoTwitterApp();
|
||||
@@ -249,11 +249,28 @@ class _promote extends \IPS\Dispatcher\Controller
|
||||
return \IPS\Theme::i()->getTemplate( 'promote' )->warningNoTwitterUser();
|
||||
}
|
||||
|
||||
/* Do we have post to page permissions? */
|
||||
$response = $account->canPostToPage();
|
||||
if ( $response !== TRUE )
|
||||
{
|
||||
/* Token stores permissions, so wipe it */
|
||||
$account->enabled = FALSE;
|
||||
$account->saveSettings( array(
|
||||
'token' => NULL,
|
||||
'secret' => NULL,
|
||||
'owner' => NULL,
|
||||
'name' => NULL
|
||||
) );
|
||||
|
||||
return \IPS\Theme::i()->getTemplate( 'promote' )->warningNoTwitterPostToPagePermission( $response );
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form;
|
||||
|
||||
if ( isset( \IPS\Request::i()->clear ) and \IPS\Request::i()->clear === 'true' )
|
||||
{
|
||||
/* We want to clear settings */
|
||||
$account->enabled = FALSE;
|
||||
$account->saveSettings( array(
|
||||
'token' => NULL,
|
||||
'secret' => NULL,
|
||||
@@ -276,6 +293,7 @@ class _promote extends \IPS\Dispatcher\Controller
|
||||
catch( \OutOfRangeException $e )
|
||||
{
|
||||
/* Member no longer exists, so clear settings */
|
||||
$account->enabled = FALSE;
|
||||
$account->saveSettings( array(
|
||||
'token' => NULL,
|
||||
'secret' => NULL,
|
||||
@@ -328,21 +346,21 @@ class _promote extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function _manageFacebook()
|
||||
{
|
||||
$facebook = \IPS\Login::getHandler('Facebook');
|
||||
$facebook = \IPS\Login\Handler::findMethod('IPS\Login\Handler\Oauth2\Facebook');
|
||||
$account = \IPS\core\Promote::getPromoter('Facebook')->setMember( \IPS\Member::loggedIn() );
|
||||
|
||||
/* Have we set up Facebook yet? */
|
||||
if ( ! $facebook->settings['app_id'] )
|
||||
if ( !$facebook OR ! $facebook->settings['client_id'] )
|
||||
{
|
||||
/* Nope, so lets do that first... */
|
||||
return \IPS\Theme::i()->getTemplate( 'promote' )->warningNoFacebookApp();
|
||||
}
|
||||
|
||||
|
||||
/* Have we synchronized our user account with Facebook? */
|
||||
if ( ! $account->connected() )
|
||||
if ( ! $facebook->canProcess( \IPS\Member::loggedIn() ) )
|
||||
{
|
||||
/* Nope, so lets do that now... */
|
||||
return \IPS\Theme::i()->getTemplate( 'promote' )->warningNoFacebookUser();
|
||||
return \IPS\Theme::i()->getTemplate( 'promote' )->warningNoFacebookUser( $facebook );
|
||||
}
|
||||
|
||||
/* Do we have post to page permissions? */
|
||||
@@ -350,7 +368,7 @@ class _promote extends \IPS\Dispatcher\Controller
|
||||
if ( $response !== TRUE )
|
||||
{
|
||||
/* Nope, so lets do that now... */
|
||||
return \IPS\Theme::i()->getTemplate( 'promote' )->warningNoFacebookPostToPagePermission( $response );
|
||||
return \IPS\Theme::i()->getTemplate( 'promote' )->warningNoFacebookPostToPagePermission( $response, $facebook );
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form;
|
||||
@@ -358,30 +376,58 @@ class _promote extends \IPS\Dispatcher\Controller
|
||||
if ( isset( \IPS\Request::i()->clear ) and \IPS\Request::i()->clear === 'true' )
|
||||
{
|
||||
/* We want to clear settings */
|
||||
$account->enabled = FALSE;
|
||||
$account->saveSettings( array(
|
||||
'token' => NULL,
|
||||
'owner' => NULL,
|
||||
'page_name' => NULL,
|
||||
'enabled' => NULL,
|
||||
'page' => NULL
|
||||
'page' => NULL,
|
||||
'group' => NULL
|
||||
) );
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=promotion&controller=promote&tab=facebook" ) );
|
||||
}
|
||||
|
||||
/* We're all set, so show the form! */
|
||||
$pages = $account->getPages();
|
||||
$pages = $facebook->getPages( \IPS\Member::loggedIn() );
|
||||
$options = array();
|
||||
$shareable = array();
|
||||
|
||||
foreach( $pages as $id => $data )
|
||||
{
|
||||
$options[ $id ] = $data[0];
|
||||
$options[ 'p_' . $id ] = \IPS\Member::loggedIn()->language()->addToStack( 'promote_facebook_page_prefix', NULL, array( 'sprintf' => array( $data[0] ) ) );
|
||||
}
|
||||
|
||||
$groups = $facebook->getGroups( \IPS\Member::loggedIn() );
|
||||
foreach( $groups as $id => $data )
|
||||
{
|
||||
$options[ 'g_' . $id ] = \IPS\Member::loggedIn()->language()->addToStack( 'promote_facebook_group_prefix', NULL, array( 'sprintf' => array( $data[0] ) ) );
|
||||
}
|
||||
|
||||
$output = '';
|
||||
$owner = \IPS\Member::load( $account->settings['owner'] );
|
||||
|
||||
if ( isset( $account->settings['shareable'] ) )
|
||||
{
|
||||
if( isset( $account->settings['shareable']['pages'] ) )
|
||||
{
|
||||
foreach( $account->settings['shareable']['pages'] as $id => $data )
|
||||
{
|
||||
$shareable[] = 'p_' . $id;
|
||||
}
|
||||
}
|
||||
|
||||
if( isset( $account->settings['shareable']['groups'] ) )
|
||||
{
|
||||
foreach( $account->settings['shareable']['groups'] as $id => $data )
|
||||
{
|
||||
$shareable[] = 'g_' . $id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $account->settings['owner'] and $account->settings['page_name'] )
|
||||
if ( $account->settings['owner'] )
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -390,6 +436,7 @@ class _promote extends \IPS\Dispatcher\Controller
|
||||
catch( \OutOfRangeException $e )
|
||||
{
|
||||
/* Member no longer exists, so clear settings */
|
||||
$account->enabled = FALSE;
|
||||
$account->saveSettings( array(
|
||||
'token' => NULL,
|
||||
'owner' => NULL,
|
||||
@@ -400,11 +447,11 @@ class _promote extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'promote_facebook_enabled', $account->enabled, FALSE, array( 'togglesOn' => array( 'promote_facebook_page', 'promote_facebook_groups', 'promote_facebook_members', 'promote_facebook_tags' ) ), NULL, NULL, NULL, 'promote_facebook_enabled' ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'promote_facebook_enabled', $account->enabled, FALSE, array( 'togglesOn' => array( 'promote_facebook_shareable', 'promote_facebook_members', 'promote_facebook_tags' ) ), NULL, NULL, NULL, 'promote_facebook_enabled' ) );
|
||||
|
||||
if ( ! $account->settings['owner'] or ( \IPS\Member::loggedIn()->member_id == $account->settings['owner'] ) )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Select( 'promote_facebook_page', $account->settings['page'], FALSE, array( 'options' => $options ), NULL, NULL, NULL, 'promote_facebook_page' ) );
|
||||
$form->add( new \IPS\Helpers\Form\CheckboxSet( 'promote_facebook_shareable', $shareable, FALSE, array( 'options' => $options ), NULL, NULL, NULL, 'promote_facebook_shareable' ) );
|
||||
}
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Stack( 'promote_facebook_tags', $account->settings['tags'], FALSE, array( 'stackFieldType' => 'Text' ), NULL, NULL, NULL, 'promote_facebook_tags' ) );
|
||||
@@ -423,13 +470,40 @@ class _promote extends \IPS\Dispatcher\Controller
|
||||
$account->enabled = $values['promote_facebook_enabled'];
|
||||
|
||||
/* If we have page data, then we are the page owner and can have extra special things */
|
||||
if ( $values['promote_facebook_page'] )
|
||||
if ( isset( $values['promote_facebook_shareable'] ) )
|
||||
{
|
||||
/* Get a non-expiring page token */
|
||||
$save['token'] = $facebook->exchangeToken( $pages[ $values['promote_facebook_page'] ][1] );
|
||||
$shareable = array( 'pages' => array(), 'groups' => array() );
|
||||
foreach( $values['promote_facebook_shareable'] as $id )
|
||||
{
|
||||
$realId = mb_substr( $id, 2 );
|
||||
|
||||
/* Page or group? */
|
||||
if ( mb_substr( $id, 0, 2 ) == 'p_' )
|
||||
{
|
||||
$shareable['pages'][ $realId ] = array(
|
||||
'token' => $facebook->exchangeToken( $pages[ $realId ][1] ),
|
||||
'name' => $pages[ $realId ][0]
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$shareable['groups'][ $realId ] = array(
|
||||
'name' => $groups[ $realId ][0]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$save['shareable'] = $shareable;
|
||||
$save['owner'] = \IPS\Member::loggedIn()->member_id;
|
||||
$save['page_name'] = $pages[ $values['promote_facebook_page'] ][0];
|
||||
$save['page'] = $values['promote_facebook_page'];
|
||||
try
|
||||
{
|
||||
$save['token'] = \IPS\Db::i()->select( 'token_access_token', 'core_login_links', array( 'token_login_method=? and token_member=?', $facebook->id, \IPS\Member::loggedIn()->member_id ) )->first();
|
||||
}
|
||||
catch( \UnderflowException $e )
|
||||
{
|
||||
$save['token'] = NULL;
|
||||
}
|
||||
|
||||
$save['tags'] = $values['promote_facebook_tags'];
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,12 @@ class _seo extends \IPS\Dispatcher\Controller
|
||||
/* Get tab content */
|
||||
$this->activeTab = \IPS\Request::i()->tab ?: 'urls';
|
||||
|
||||
\IPS\Output::i()->sidebar['actions']['rebuildsitemap'] = array(
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=promotion&controller=seo&do=rebuildSitemap' ),
|
||||
'title' => 'rebuild_sitemap',
|
||||
'icon' => 'history'
|
||||
);
|
||||
|
||||
parent::execute();
|
||||
}
|
||||
|
||||
@@ -50,7 +56,7 @@ class _seo extends \IPS\Dispatcher\Controller
|
||||
protected function manage()
|
||||
{
|
||||
/* Work out output */
|
||||
$activeTabContents = call_user_func( array( $this, '_manage' . ucfirst( $this->activeTab ) ) );
|
||||
$activeTabContents = call_user_func( array( $this, '_manage' . mb_ucfirst( $this->activeTab ) ) );
|
||||
|
||||
/* If this is an AJAX request, just return it */
|
||||
if( \IPS\Request::i()->isAjax() )
|
||||
@@ -142,6 +148,7 @@ class _seo extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/* Init */
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->addMessage( 'sitemap_blurb', 'ipsMessage ipsMessage_info' );
|
||||
$form->add( new \IPS\Helpers\Form\Url( 'sitemap_url', \IPS\Settings::i()->sitemap_url ?: \IPS\Settings::i()->base_url . 'sitemap.php', FALSE ) );
|
||||
|
||||
/* Get extension settings */
|
||||
@@ -206,6 +213,7 @@ class _seo extends \IPS\Dispatcher\Controller
|
||||
|
||||
if( !$form->error )
|
||||
{
|
||||
$values['sitemap_url'] = (string) $values['sitemap_url'];
|
||||
$form->saveAsSettings( $values );
|
||||
|
||||
foreach( \IPS\Application::allExtensions( 'core', 'Sitemap', FALSE, 'core' ) as $extKey => $extension )
|
||||
@@ -223,7 +231,7 @@ class _seo extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
return \IPS\Theme::i()->getTemplate( 'forms' )->blurb( 'sitemap_blurb' ) . $form;
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -390,7 +398,7 @@ class _seo extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->class = 'ipsForm_vertical';
|
||||
$form->class = 'ipsForm_vertical ipsPad';
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'metatag_url', $url, FALSE, array( 'placeholder' => 'profile/*' ), NULL, \IPS\Settings::i()->base_url ) );
|
||||
$form->hiddenValues['original_url'] = $url;
|
||||
|
||||
@@ -502,4 +510,21 @@ FILE;
|
||||
\IPS\Output::i()->sendOutput( $htaccess, 200, 'application/x-htaccess', array( 'Content-Disposition' => 'attachment; filename=.htaccess' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger the sitemap rebuild
|
||||
*/
|
||||
protected function rebuildSitemap()
|
||||
{
|
||||
/* truncate sitemap */
|
||||
\IPS\Db::i()->delete( 'core_sitemap' );
|
||||
|
||||
$extensions = \IPS\Application::allExtensions( 'core', 'Sitemap', new \IPS\Member, 'core' );
|
||||
foreach ( $extensions as $k => $extension )
|
||||
{
|
||||
\IPS\Task::queue( 'core', 'RebuildSitemap', array( 'extensionKey' => $k ), 5 );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=promotion&controller=seo" ), 'rebuild_sitemap_initialized' );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -45,11 +45,11 @@ class _advanced extends \IPS\Dispatcher\Controller
|
||||
\IPS\Request::i()->tab = isset( \IPS\Request::i()->tab ) ? \IPS\Request::i()->tab : 'settings';
|
||||
if ( $pos = mb_strpos( \IPS\Request::i()->tab, '-' ) )
|
||||
{
|
||||
$activeTabContents = call_user_func( array( $this, '_manage'.ucfirst( mb_substr( \IPS\Request::i()->tab, 0, $pos ) ) ), mb_substr( \IPS\Request::i()->tab, $pos + 1 ) );
|
||||
$activeTabContents = call_user_func( array( $this, '_manage' . mb_ucfirst( mb_substr( \IPS\Request::i()->tab, 0, $pos ) ) ), mb_substr( \IPS\Request::i()->tab, $pos + 1 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
$activeTabContents = call_user_func( array( $this, '_manage'.ucfirst( \IPS\Request::i()->tab ) ) );
|
||||
$activeTabContents = call_user_func( array( $this, '_manage' . mb_ucfirst( \IPS\Request::i()->tab ) ) );
|
||||
}
|
||||
|
||||
/* If this is an AJAX request, just return it */
|
||||
@@ -99,10 +99,7 @@ class _advanced extends \IPS\Dispatcher\Controller
|
||||
/* Clear it */
|
||||
\IPS\Data\Cache::i()->clearAll();
|
||||
\IPS\Data\Store::i()->clearAll();
|
||||
|
||||
/* Enable/disable the clearcaches task */
|
||||
\IPS\Db::i()->update( 'core_tasks', array( 'enabled' => intval( \IPS\CACHE_METHOD === 'None' and \IPS\CACHE_PAGE_TIMEOUT ) ), "`key`='clearcache'" );
|
||||
|
||||
|
||||
/* Log and redirect */
|
||||
\IPS\Session::i()->log( 'acplogs__datastore_settings_updated' );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=settings&controller=advanced&tab=datastore' ), 'saved' );
|
||||
@@ -149,7 +146,7 @@ class _advanced extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
if ( !$input->htmlId )
|
||||
{
|
||||
$input->htmlId = md5( uniqid() );
|
||||
$input->htmlId = md5( mt_rand() );
|
||||
}
|
||||
|
||||
$extra[] = $input;
|
||||
@@ -170,7 +167,7 @@ class _advanced extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Cache */
|
||||
$extra = array();
|
||||
$toggles = array();
|
||||
$toggles = array( 'Redis' => array( 'redis_enabled' ) );
|
||||
$disabled = array();
|
||||
$cacheConfigurationFields = array();
|
||||
$options = array(
|
||||
@@ -200,7 +197,7 @@ class _advanced extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
if ( !$input->htmlId )
|
||||
{
|
||||
$input->htmlId = md5( uniqid() );
|
||||
$input->htmlId = md5( mt_rand() );
|
||||
}
|
||||
|
||||
$extra[] = $input;
|
||||
@@ -218,6 +215,9 @@ class _advanced extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$form->add( $input );
|
||||
}
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'redis_enabled', \IPS\REDIS_ENABLED, FALSE, array(), NULL, NULL, NULL, 'redis_enabled' ) );
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'cache_guest_page', \IPS\CACHE_PAGE_TIMEOUT, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'disable' ), NULL, \IPS\Member::loggedIn()->language()->addToStack('for'), \IPS\Member::loggedIn()->language()->addToStack('seconds'), 'cache_guest_page' ) );
|
||||
|
||||
/* Handle submissions */
|
||||
@@ -242,7 +242,7 @@ class _advanced extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/* If we've changed anything, explain to the admin they have to update */
|
||||
if ( $values['datastore_method'] !== \IPS\STORE_METHOD or str_replace( '\\/', '/', json_encode( $storeConfiguration ) ) !== \IPS\STORE_CONFIG or $values['cache_method'] !== \IPS\CACHE_METHOD or json_encode( $cacheConfiguration ) !== \IPS\CACHE_CONFIG or $values['cache_guest_page'] !== \IPS\CACHE_PAGE_TIMEOUT )
|
||||
if ( $values['datastore_method'] !== \IPS\STORE_METHOD or str_replace( '\\/', '/', json_encode( $storeConfiguration ) ) !== \IPS\STORE_CONFIG or $values['cache_method'] !== \IPS\CACHE_METHOD or json_encode( $cacheConfiguration ) !== \IPS\CACHE_CONFIG or $values['cache_guest_page'] !== \IPS\CACHE_PAGE_TIMEOUT or \IPS\REDIS_ENABLED != (boolean) $values['redis_enabled'] )
|
||||
{
|
||||
/* Connect to cache engine if we can and invalidate any existing caches */
|
||||
try
|
||||
@@ -256,17 +256,22 @@ class _advanced extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
catch( \Exception $e ){}
|
||||
|
||||
/* Enable/disable the clearcaches task */
|
||||
\IPS\Db::i()->update( 'core_tasks', array( 'enabled' => intval( $values['cache_method'] === 'None' and $values['cache_guest_page'] ) ), "`key`='clearcache'" );
|
||||
|
||||
/* Invalidate any existing datastore records */
|
||||
try
|
||||
{
|
||||
$classname = 'IPS\Data\Store\\' . $values['datastore_method'];
|
||||
$instance = new $classname( $storeConfiguration );
|
||||
$instance->clearAll();
|
||||
}
|
||||
catch( \Exception $e ){}
|
||||
|
||||
/* Reset the last update flag for data store */
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => time() ), array( 'conf_key=?', 'last_data_store_update' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
\IPS\Settings::i()->changeValues( array( 'last_data_store_update' => time() ) );
|
||||
|
||||
/* Display */
|
||||
$downloadUrl = \IPS\Http\Url::internal( 'app=core&module=settings&controller=advanced&do=downloadDatastoreConstants' )->setQueryString( array( 'store_method' => $values['datastore_method'], 'store_config' => str_replace( '\\/', '/', json_encode( $storeConfiguration ) ), 'cache_method' => $values['cache_method'], 'cache_config' => json_encode( $cacheConfiguration ), 'cache_guest_page' => $values['cache_guest_page'] ) );
|
||||
$checkUrl = \IPS\Http\Url::internal( 'app=core&module=settings&controller=advanced&tab=datastore&checkConstants=1' )->setQueryString( array( 'store_method' => $values['datastore_method'], 'store_config' => str_replace( '\\/', '/', json_encode( $storeConfiguration ) ), 'cache_method' => $values['cache_method'], 'cache_config' => json_encode( $cacheConfiguration ), 'cache_guest_page' => $values['cache_guest_page'] ) );
|
||||
$downloadUrl = \IPS\Http\Url::internal( 'app=core&module=settings&controller=advanced&do=downloadDatastoreConstants' )->setQueryString( array( 'store_method' => $values['datastore_method'], 'store_config' => str_replace( '\\/', '/', json_encode( $storeConfiguration ) ), 'cache_method' => $values['cache_method'], 'cache_config' => json_encode( $cacheConfiguration ), 'cache_guest_page' => $values['cache_guest_page'], 'redis_enabled' => $values['redis_enabled'] ) );
|
||||
$checkUrl = \IPS\Http\Url::internal( 'app=core&module=settings&controller=advanced&tab=datastore&checkConstants=1' )->setQueryString( array( 'store_method' => $values['datastore_method'], 'store_config' => str_replace( '\\/', '/', json_encode( $storeConfiguration ) ), 'cache_method' => $values['cache_method'], 'cache_config' => json_encode( $cacheConfiguration ), 'cache_guest_page' => $values['cache_guest_page'], 'redis_enabled' => $values['redis_enabled'] ) );
|
||||
return \IPS\Theme::i()->getTemplate( 'settings' )->dataStoreChange( $downloadUrl, $checkUrl );
|
||||
}
|
||||
/* Otherwise just log and redirect */
|
||||
@@ -293,19 +298,38 @@ class _advanced extends \IPS\Dispatcher\Controller
|
||||
foreach ( \IPS\IPS::defaultConstants() as $k => $v )
|
||||
{
|
||||
$val = constant( 'IPS\\' . $k );
|
||||
if ( $val !== $v and !in_array( $k, array( 'STORE_METHOD', 'STORE_CONFIG', 'CACHE_METHOD', 'CACHE_CONFIG', 'CACHE_PAGE_TIMEOUT', 'SUITE_UNIQUE_KEY' ) ) )
|
||||
|
||||
if ( $val !== $v and !in_array( $k, array( 'STORE_METHOD', 'STORE_CONFIG', 'CACHE_METHOD', 'CACHE_CONFIG', 'CACHE_PAGE_TIMEOUT', 'SUITE_UNIQUE_KEY', 'READ_WRITE_SEPARATION', 'REDIS_ENABLED' ) ) )
|
||||
{
|
||||
$output .= "define( '{$k}', " . var_export( $val, TRUE ) . " );\n";
|
||||
}
|
||||
}
|
||||
|
||||
/* We have to treat READ_WRITE_SEPARATION special because admin/index.php always disables it */
|
||||
if( \file_exists( \IPS\ROOT_PATH . '/constants.php' ) )
|
||||
{
|
||||
$constants = \file_get_contents( \IPS\ROOT_PATH . '/constants.php' );
|
||||
|
||||
/* Did we sniff the constant out with a quick check? */
|
||||
if( mb_strpos( $constants, 'READ_WRITE_SEPARATION' ) )
|
||||
{
|
||||
preg_match( "/define\(\s*?['\"]READ_WRITE_SEPARATION[\"']\s*?,\s*?(.+?)\);/i", $constants, $matches );
|
||||
|
||||
if( isset( $matches[1] ) )
|
||||
{
|
||||
$output .= "define( 'READ_WRITE_SEPARATION', " . $matches[1] . " );\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$output .= "\n";
|
||||
$output .= "define( 'REDIS_ENABLED', " . var_export( (boolean) \IPS\Request::i()->redis_enabled, TRUE ) . " );\n";
|
||||
$output .= "define( 'STORE_METHOD', " . var_export( \IPS\Request::i()->store_method, TRUE ) . " );\n";
|
||||
$output .= "define( 'STORE_CONFIG', " . var_export( \IPS\Request::i()->store_config, TRUE ) . " );\n";
|
||||
$output .= "define( 'CACHE_METHOD', " . var_export( \IPS\Request::i()->cache_method, TRUE ) . " );\n";
|
||||
$output .= "define( 'CACHE_CONFIG', " . var_export( \IPS\Request::i()->cache_config, TRUE ) . " );\n";
|
||||
$output .= "define( 'CACHE_PAGE_TIMEOUT', " . var_export( (int) \IPS\Request::i()->cache_guest_page, TRUE ) . " );\n";
|
||||
$output .= "define( 'SUITE_UNIQUE_KEY', " . var_export( mb_substr( md5( uniqid() ), 10, 10 ), TRUE ) . " );\n"; // Regenerate the unique key so there's no conflicts
|
||||
$output .= "define( 'SUITE_UNIQUE_KEY', " . var_export( mb_substr( md5( mt_rand() ), 10, 10 ), TRUE ) . " );\n"; // Regenerate the unique key so there's no conflicts
|
||||
$output .= "\n\n\n";
|
||||
|
||||
\IPS\Output::i()->sendOutput( $output, 200, 'text/x-php', array( 'Content-Disposition' => 'attachment; filename=constants.php' ) );
|
||||
@@ -323,9 +347,7 @@ class _advanced extends \IPS\Dispatcher\Controller
|
||||
/* Generate a cron key if we don't have one */
|
||||
if ( !\IPS\Settings::i()->task_cron_key )
|
||||
{
|
||||
\IPS\Settings::i()->task_cron_key = md5( uniqid() );
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => \IPS\Settings::i()->task_cron_key ), array( 'conf_key=?', 'task_cron_key' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
\IPS\Settings::i()->changeValues( array( 'task_cron_key' => md5( mt_rand() ) ) );
|
||||
}
|
||||
|
||||
/* Sort stuff out for the cron setting */
|
||||
@@ -372,6 +394,7 @@ class _advanced extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Build and show form */
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->addHeader('task_manager');
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'task_use_cron', \IPS\CIC ? 'ips' : \IPS\Settings::i()->task_use_cron, FALSE, $options, function ( $val )
|
||||
{
|
||||
$cronFile = \IPS\ROOT_PATH . '/applications/core/interface/task/task.php';
|
||||
@@ -380,6 +403,17 @@ class _advanced extends \IPS\Dispatcher\Controller
|
||||
throw new \DomainException( \IPS\Member::loggedIn()->language()->addToStack('task_use_cron_executable', FALSE, array( 'sprintf' => array( $cronFile ) ) ) );
|
||||
}
|
||||
}, NULL, NULL, 'task_use_cron' ) );
|
||||
$form->addHeader( 'security_header_ips' );
|
||||
if ( !\IPS\CIC )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'xforward_matching', \IPS\Settings::i()->xforward_matching, FALSE ) );
|
||||
}
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'match_ipaddress', \IPS\Settings::i()->match_ipaddress, FALSE ) );
|
||||
if( \IPS\BYPASS_ACP_IP_CHECK === TRUE )
|
||||
{
|
||||
\IPS\Member::loggedIn()->language()->words['match_ipaddress_warning'] = \IPS\Member::loggedIn()->language()->addToStack('ip_override_warn');
|
||||
}
|
||||
$form->addHeader('performance_settings');
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'widget_cache_ttl', ( isset( \IPS\Settings::i()->widget_cache_ttl ) ) ? \IPS\Settings::i()->widget_cache_ttl : 60, FALSE, array( 'min' => 60 ), NULL, \IPS\Member::loggedIn()->language()->addToStack('for'), \IPS\Member::loggedIn()->language()->addToStack('seconds') ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'auto_polling_enabled', \IPS\Settings::i()->auto_polling_enabled, FALSE ) );
|
||||
|
||||
@@ -417,11 +451,18 @@ class _advanced extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'advanced_manage_tasks' );
|
||||
|
||||
$table = new \IPS\Helpers\Table\Db( 'core_tasks', \IPS\Http\Url::internal( 'app=core&module=settings&controller=advanced&do=tasks' ) );
|
||||
$table = new \IPS\Helpers\Table\Db( 'core_tasks', \IPS\Http\Url::internal( 'app=core&module=settings&controller=advanced&do=tasks' ), array( array( 'a.app_enabled=1' ) ) );
|
||||
$table->joins = array(
|
||||
array( 'select' => 'a.app_enabled', 'from' => array( 'core_applications', 'a' ), 'where' => "a.app_directory=app" )
|
||||
);
|
||||
$table->langPrefix = 'task_manager_';
|
||||
$table->include = array( 'app', 'key', 'frequency', 'next_run', 'last_run' );
|
||||
$table->mainColumn = 'key';
|
||||
$table->quickSearch = 'key';
|
||||
|
||||
$table->primarySortBy = 'enabled';
|
||||
$table->primarySortDirection = 'DESC';
|
||||
|
||||
$table->sortBy = $table->sortBy ?: 'next_run';
|
||||
$table->sortDirection = $table->sortDirection ?: 'asc';
|
||||
$table->quickSearch = function( $val )
|
||||
@@ -429,11 +470,11 @@ class _advanced extends \IPS\Dispatcher\Controller
|
||||
$matches = \IPS\Member::loggedIn()->language()->searchCustom( 'task__', $val, TRUE );
|
||||
if ( count( $matches ) )
|
||||
{
|
||||
return '(' . \IPS\Db::i()->in( '`key`', array_keys( $matches ) ) . " OR `key` LIKE '%{$val}%')";
|
||||
return array( '(' . \IPS\Db::i()->in( '`key`', array_keys( $matches ) ) . " OR `key` LIKE '%{$val}%')" );
|
||||
}
|
||||
else
|
||||
{
|
||||
return "`key` LIKE '%{$val}%'";
|
||||
return array( "`key` LIKE '%" . \IPS\Db::i()->escape_string( $val ) . "%'" );
|
||||
}
|
||||
};
|
||||
|
||||
@@ -603,6 +644,10 @@ class _advanced extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'advancedsettings' )->taskResult( TRUE, $output, $task->id );
|
||||
}
|
||||
}
|
||||
catch( \RuntimeException $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'task_class_not_found', '4C124/6', 404, '' );
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C124/1', 404, '' );
|
||||
@@ -803,7 +848,14 @@ class _advanced extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'furl_friendly', $current ? $current['friendly'] : '', FALSE, array(), NULL, \IPS\Settings::i()->base_url . ( \IPS\Settings::i()->htaccess_mod_rewrite ? '' : 'index.php?/' ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'furl_friendly', $current ? $current['friendly'] : '', FALSE, array( 'placeholder' => \IPS\Member::loggedIn()->language()->addToStack('furl_friendly_placeholder') ), function( $val )
|
||||
{
|
||||
if( mb_substr( $val, 0, 3 ) == '{?}' )
|
||||
{
|
||||
throw new \DomainException( 'furl_too_greedy' );
|
||||
}
|
||||
},
|
||||
\IPS\Settings::i()->base_url . ( \IPS\Settings::i()->htaccess_mod_rewrite ? '' : 'index.php?/' ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'furl_real', $current ? $current['real'] : '', FALSE, array(), NULL, \IPS\Settings::i()->base_url . 'index.php?' ) );
|
||||
|
||||
if ( $values = $form->values() )
|
||||
@@ -853,15 +905,17 @@ class _advanced extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
else
|
||||
{
|
||||
$key = 'key' . ( count( $furl ) + 1 );
|
||||
ksort( $furl );
|
||||
$keys = array_keys( $furl );
|
||||
$lastKey = str_replace( 'key', '', end( $keys ) );
|
||||
$key = 'key' . ( $lastKey + 1 );
|
||||
$furl[ $key ] = $save;
|
||||
}
|
||||
|
||||
\IPS\Session::i()->log( 'acplogs__advanced_furl_edited' );
|
||||
|
||||
$newValue = json_encode( $furl );
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => $newValue ), array( 'conf_key=?', 'furl_configuration' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
\IPS\Settings::i()->changeValues( array( 'furl_configuration' => $newValue ) );
|
||||
|
||||
/* Clear Sidebar Caches */
|
||||
\IPS\Widget::deleteCaches();
|
||||
@@ -895,8 +949,7 @@ class _advanced extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
unset( $furlDefinition[ \IPS\Request::i()->key ] );
|
||||
$newValue = json_encode( $furlDefinition );
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => $newValue ), array( 'conf_key=?', 'furl_configuration' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
\IPS\Settings::i()->changeValues( array( 'furl_configuration' => $newValue ) );
|
||||
|
||||
/* Clear guest page caches */
|
||||
\IPS\Data\Cache::i()->clearAll();
|
||||
@@ -916,8 +969,7 @@ class _advanced extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'advanced_manage_furls' );
|
||||
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => NULL ), array( 'conf_key=?', 'furl_configuration' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
\IPS\Settings::i()->changeValues( array( 'furl_configuration' => NULL ) );
|
||||
unset( \IPS\Data\Store::i()->furl_configuration );
|
||||
|
||||
/* Clear guest page caches */
|
||||
|
||||
@@ -42,9 +42,17 @@ class _contactus extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$form = $this->_getConfigForm();
|
||||
|
||||
if ( $values = $form->values() )
|
||||
if ( $values = $form->values( true ) )
|
||||
{
|
||||
$form->saveAsSettings();
|
||||
/* If we unselect 'everyone' and save, an empty string is passed through, so the default value is picked up in Settings::changeValues(),
|
||||
which is the 'everyone' preference...the end result is that everyone gets rechecked when you uncheck it. To counter that, we'll store an invalid
|
||||
value here. */
|
||||
if( $values['contact_access'] === '' )
|
||||
{
|
||||
$values['contact_access'] = '-1';
|
||||
}
|
||||
|
||||
$form->saveAsSettings( $values );
|
||||
|
||||
/* Clear guest page caches */
|
||||
\IPS\Data\Cache::i()->clearAll();
|
||||
|
||||
@@ -49,22 +49,18 @@ class _email extends \IPS\Dispatcher\Controller
|
||||
$settingsForm->add( new \IPS\Helpers\Form\Email( 'email_in', \IPS\Settings::i()->email_in, TRUE ) );
|
||||
$settingsForm->add( new \IPS\Helpers\Form\Color( 'email_color', \IPS\Settings::i()->email_color, TRUE ) );
|
||||
$settingsForm->add( new \IPS\Helpers\Form\Upload( 'email_logo', \IPS\Settings::i()->email_logo ? \IPS\File::get( 'core_Theme', \IPS\Settings::i()->email_logo ) : NULL, FALSE, array( 'image' => TRUE, 'storageExtension' => 'core_Theme' ) ) );
|
||||
|
||||
$settingsForm->add( new \IPS\Helpers\Form\YesNo( 'social_links_in_email', \IPS\Settings::i()->social_links_in_email, FALSE, array(), NULL, NULL, NULL, 'social_links_in_email' ) );
|
||||
|
||||
if ( \IPS\Settings::i()->promote_community_enabled )
|
||||
{
|
||||
$settingsForm->add( new \IPS\Helpers\Form\YesNo( 'our_picks_in_email', \IPS\Settings::i()->our_picks_in_email, FALSE, array(), NULL, NULL, NULL, 'our_picks_in_email' ) );
|
||||
}
|
||||
|
||||
$settingsForm->addHeader( 'advanced_settings' );
|
||||
|
||||
$method = \IPS\Settings::i()->mail_method;
|
||||
$disabled = array();
|
||||
if ( \IPS\Settings::i()->sparkpost_api_key )
|
||||
{
|
||||
if ( \IPS\Settings::i()->sparkpost_use_for == 2 )
|
||||
{
|
||||
$method = 'sparkpost';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$disabled[] = 'sparkpost';
|
||||
}
|
||||
|
||||
if ( \IPS\Settings::i()->sendgrid_api_key )
|
||||
{
|
||||
if ( \IPS\Settings::i()->sendgrid_use_for == 2 )
|
||||
@@ -76,12 +72,18 @@ class _email extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$disabled[] = 'sendgrid';
|
||||
}
|
||||
|
||||
|
||||
/* We previously renamed this to 'php' */
|
||||
if( $method == 'mail' )
|
||||
{
|
||||
$method = 'php';
|
||||
}
|
||||
|
||||
$settingsForm->add( new \IPS\Helpers\Form\Radio( 'mail_method', $method, TRUE, array(
|
||||
'options' => array( 'php' => ( \IPS\CIC ? 'mail_method_cic' : 'mail_method_php' ), 'smtp' => 'mail_method_smtp', 'sendgrid' => 'mail_method_sendgrid', 'sparkpost' => 'mail_method_sparkpost' ),
|
||||
'options' => array( 'php' => ( \IPS\CIC ? 'mail_method_cic' : 'mail_method_php' ), 'smtp' => 'mail_method_smtp', 'sendgrid' => 'mail_method_sendgrid' ),
|
||||
'disabled' => $disabled,
|
||||
'toggles' => array(
|
||||
'mail' => array( 'php_mail_extra' ),
|
||||
'php' => array( 'php_mail_extra' ),
|
||||
'smtp' => array( 'smtp_host', 'smtp_port', 'smtp_user', 'smtp_pass', 'smtp_helo', 'smtp_protocol' ),
|
||||
)
|
||||
) ) );
|
||||
@@ -107,15 +109,6 @@ class _email extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
if ( $values['mail_method'] != 'sparkpost' and \IPS\Settings::i()->sparkpost_use_for == 2 )
|
||||
{
|
||||
$values['sparkpost_use_for'] = 1;
|
||||
}
|
||||
elseif ( $values['mail_method'] == 'sparkpost' )
|
||||
{
|
||||
$values['sparkpost_use_for'] = 2;
|
||||
}
|
||||
|
||||
if ( $values['mail_method'] != 'sendgrid' and \IPS\Settings::i()->sendgrid_use_for == 2 )
|
||||
{
|
||||
$values['sendgrid_use_for'] = 1;
|
||||
@@ -125,6 +118,11 @@ class _email extends \IPS\Dispatcher\Controller
|
||||
$values['sendgrid_use_for'] = 2;
|
||||
}
|
||||
|
||||
if ( $values['email_logo'] )
|
||||
{
|
||||
$values['email_logo'] = (string) $values['email_logo'];
|
||||
}
|
||||
|
||||
$settingsForm->saveAsSettings( $values );
|
||||
\IPS\Session::i()->log( 'acplogs__email_settings' );
|
||||
|
||||
@@ -239,7 +237,7 @@ class _email extends \IPS\Dispatcher\Controller
|
||||
$val = \IPS\Member::loggedIn()->language()->get('phpmail_not_sent');
|
||||
}
|
||||
|
||||
return \IPS\Theme::i()->getTemplate( 'logs' )->emailErrorLog( nl2br( htmlspecialchars( $val, \IPS\HTMLENTITIES, 'UTF-8', FALSE ) ), $row );
|
||||
return \IPS\Theme::i()->getTemplate( 'logs' )->emailErrorLog( nl2br( htmlspecialchars( $val, ENT_DISALLOWED, 'UTF-8', FALSE ) ), $row );
|
||||
},
|
||||
'mlog_content' => function( $val, $row )
|
||||
{
|
||||
|
||||
@@ -48,9 +48,13 @@ class _general extends \IPS\Dispatcher\Controller
|
||||
$form->add( new \IPS\Helpers\Form\Editor( 'site_offline_message', \IPS\Settings::i()->site_offline_message, FALSE, array( 'app' => 'core', 'key' => 'Admin', 'autoSaveKey' => 'onlineoffline', 'attachIds' => array( NULL, NULL, 'site_offline_message' ) ), NULL, NULL, NULL, 'site_offline_message_id' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Address( 'site_address', \IPS\GeoLocation::buildFromJson( \IPS\Settings::i()->site_address ), FALSE ) );
|
||||
$form->add( new \IPS\Helpers\Form\Stack( 'site_social_profiles', \IPS\Settings::i()->site_social_profiles ? json_decode( \IPS\Settings::i()->site_social_profiles, true ) : array(), FALSE, array( 'stackFieldType' => '\IPS\core\Form\SocialProfiles', 'maxItems' => 50, 'key' => array( 'placeholder' => 'http://example.com', 'size' => 20 ) ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'site_twitter_id', \IPS\Settings::i()->site_twitter_id, FALSE, array( 'placeholder' => \IPS\Member::loggedIn()->language()->addToStack('site_twitter_id_placeholder'), 'size' => 20 ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Translatable( 'copyright_line', NULL, FALSE, array( 'app' => 'core', 'key' => 'copyright_line_value', 'placeholder' => \IPS\Member::loggedIn()->language()->addToStack('copyright_line_placeholder') ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Stack( 'upgrade_email', explode( ',', \IPS\Settings::i()->upgrade_email ), FALSE, array( 'stackFieldType' => 'Email', 'maxItems' => 5 ) ) );
|
||||
// $form->add( new \IPS\Helpers\Form\YesNo( 'diagnostics_reporting', \IPS\Settings::i()->diagnostics_reporting ) );
|
||||
/* $form->add( new \IPS\Helpers\Form\CheckboxSet( 'diagnostics_reporting', array( 'usage' => ( (bool) \IPS\Settings::i()->usage_reporting ), 'diagnostics' => ( (bool) \IPS\Settings::i()->diagnostics_reporting ) ), FALSE, array( 'options' => array(
|
||||
'usage' => 'diagnostics_reporting_usage',
|
||||
'diagnostics' => 'diagnostics_reporting_diagnostics',
|
||||
) ) ) ); */
|
||||
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
@@ -61,6 +65,12 @@ class _general extends \IPS\Dispatcher\Controller
|
||||
return (bool) $value['key'];
|
||||
} ) );
|
||||
$values['site_address'] = json_encode( $values['site_address'] );
|
||||
|
||||
$values['upgrade_email'] = implode( ',', $values['upgrade_email'] );
|
||||
|
||||
$values['usage_reporting'] = in_array( 'usage', $values['diagnostics_reporting'] );
|
||||
$values['diagnostics_reporting'] = in_array( 'diagnostics', $values['diagnostics_reporting'] );
|
||||
\IPS\Db::i()->update( 'core_tasks', array( 'enabled' => intval( $values['usage_reporting'] ) ), array( '`key`=?', 'usagereporting' ) );
|
||||
|
||||
$form->saveAsSettings( $values );
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Login Handlers
|
||||
* @brief Login Methods
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 15 Mar 2013
|
||||
* @since 12 May 2017
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\admin\settings;
|
||||
@@ -18,14 +18,19 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
}
|
||||
|
||||
/**
|
||||
* Login Handlers
|
||||
* Login Methods
|
||||
*/
|
||||
class _login extends \IPS\Node\Controller
|
||||
{
|
||||
/**
|
||||
* Node Class
|
||||
*/
|
||||
protected $nodeClass = 'IPS\Login\LoginAbstract';
|
||||
protected $nodeClass = 'IPS\Login\Handler';
|
||||
|
||||
/**
|
||||
* Show the "add" button in the page root rather than the table root
|
||||
*/
|
||||
protected $_addButtonInRoot = FALSE;
|
||||
|
||||
/**
|
||||
* Execute
|
||||
@@ -34,54 +39,170 @@ class _login extends \IPS\Node\Controller
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'login_manage' );
|
||||
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'login_access' );
|
||||
return parent::execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Root Buttons
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function _getRootButtons()
|
||||
{
|
||||
$buttons = parent::_getRootButtons();
|
||||
|
||||
if ( isset( $buttons['add'] ) )
|
||||
{
|
||||
$buttons['add']['link'] = $buttons['add']['link']->setQueryString( '_new', 1 );
|
||||
}
|
||||
|
||||
return $buttons;
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage
|
||||
*
|
||||
* @return void
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
{
|
||||
\IPS\Output::i()->sidebar['actions'] = array(
|
||||
'settings' => array(
|
||||
'title' => 'login_settings',
|
||||
'icon' => 'cog',
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=settings&controller=login&do=settings' ),
|
||||
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('login_settings') )
|
||||
),
|
||||
'forcelogout' => array(
|
||||
'title' => 'force_all_logout',
|
||||
'icon' => 'lock',
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=settings&controller=login&do=forceLogout' ),
|
||||
'data' => array( 'confirm' => '' ),
|
||||
),
|
||||
);
|
||||
/* Work out tabs */
|
||||
$tabs = array();
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'settings', 'login_manage' ) )
|
||||
{
|
||||
$tabs['handlers'] = 'login_handlers';
|
||||
}
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'settings', 'login_settings' ) )
|
||||
{
|
||||
$tabs['settings'] = 'login_settings';
|
||||
}
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'settings', 'registration_settings' ) )
|
||||
{
|
||||
$tabs['registration'] = 'registration_settings';
|
||||
}
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'settings', 'login_account_management' ) )
|
||||
{
|
||||
$tabs['accountsettings'] = 'account_management_settings';
|
||||
}
|
||||
|
||||
/* Show IPS Connect "master" information */
|
||||
$masterUrl = \IPS\Http\Url::internal( 'applications/core/interface/ipsconnect/ipsconnect.php', 'none' );
|
||||
$masterKey = \IPS\CONNECT_MASTER_KEY ?: md5( md5( \IPS\Settings::i()->sql_user . \IPS\Settings::i()->sql_pass ) . \IPS\Settings::i()->board_start );
|
||||
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global' )->message( \IPS\Member::loggedIn()->language()->addToStack( 'login_ipsconnect_info', FALSE, array( 'sprintf' => array( $masterUrl, $masterKey ) ) ), 'info', NULL, FALSE );
|
||||
|
||||
return parent::manage();
|
||||
/* Get active tab */
|
||||
if ( isset( \IPS\Request::i()->tab ) and isset( $tabs[ \IPS\Request::i()->tab ] ) )
|
||||
{
|
||||
$activeTab = \IPS\Request::i()->tab;
|
||||
}
|
||||
else
|
||||
{
|
||||
$_tabs = array_keys( $tabs ) ;
|
||||
$activeTab = array_shift( $_tabs );
|
||||
}
|
||||
|
||||
/* Get active tab contents */
|
||||
$output = '';
|
||||
switch ( $activeTab )
|
||||
{
|
||||
case 'handlers':
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'login_manage' );
|
||||
parent::manage();
|
||||
$output = \IPS\Output::i()->output;
|
||||
break;
|
||||
case 'settings':
|
||||
$output = $this->_settings();
|
||||
break;
|
||||
case 'registration':
|
||||
$output = $this->_registration();
|
||||
break;
|
||||
case 'accountsettings':
|
||||
$output = $this->_accountsettings();
|
||||
break;
|
||||
}
|
||||
|
||||
/* Output */
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__core_settings_login');
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->output = $output;
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->sidebar['actions'] = array(
|
||||
'forcelogout' => array(
|
||||
'title' => 'force_all_logout',
|
||||
'icon' => 'lock',
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=settings&controller=login&do=forceLogout' ),
|
||||
'data' => array( 'confirm' => '' ),
|
||||
),
|
||||
);
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global', 'core' )->tabs( $tabs, $activeTab, $output, \IPS\Http\Url::internal( "app=core&module=settings&controller=login" ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Force all users to be logged out
|
||||
* Add/Edit Form
|
||||
*
|
||||
* @return void
|
||||
* @return void
|
||||
*/
|
||||
protected function forceLogout()
|
||||
protected function form()
|
||||
{
|
||||
\IPS\Db::i()->update( 'core_members_known_devices', array( 'login_key' => NULL ) );
|
||||
\IPS\Db::i()->delete( 'core_sessions' );
|
||||
|
||||
\IPS\Session::i()->log( 'acplogs__logout_force' );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=settings&controller=login' ), 'logged_out_force' );
|
||||
if ( \IPS\Request::i()->id )
|
||||
{
|
||||
return parent::form();
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->output = new \IPS\Helpers\Wizard( array(
|
||||
'login_handler' => function( $data )
|
||||
{
|
||||
$options = array();
|
||||
foreach ( \IPS\Login\Handler::handlerClasses() as $class )
|
||||
{
|
||||
if ( !$class::$allowMultiple )
|
||||
{
|
||||
foreach ( \IPS\Login\Handler::roots() as $handler )
|
||||
{
|
||||
if ( $handler instanceof $class )
|
||||
{
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
$options[ $class ] = $class::getTitle();
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form( 'login_handler_1', 'continue' );
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'login_handler', TRUE, NULL, array( 'options' => $options ) ) );
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
return array( 'handler' => $values['login_handler'] );
|
||||
}
|
||||
return $form;
|
||||
},
|
||||
'login_details' => function( $data )
|
||||
{
|
||||
$node = new $data['handler'];
|
||||
$node->classname = $data['handler'];
|
||||
$form = $this->_addEditForm( $node );
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
try
|
||||
{
|
||||
$node->settings = array();
|
||||
$node->order = \IPS\Db::i()->select( 'MAX(login_order)', $node::$databaseTable )->first() + 1;
|
||||
$node->saveForm( $node->formatFormValues( $values ) );
|
||||
|
||||
\IPS\Session::i()->log( 'acplog__node_created', array( $this->title => TRUE, $node->titleForLog() => FALSE ) );
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=core&module=settings&controller=login') );
|
||||
}
|
||||
catch ( \LogicException $e )
|
||||
{
|
||||
$form->error = $e->getMessage();
|
||||
}
|
||||
}
|
||||
return $form;
|
||||
}
|
||||
), \IPS\Http\Url::internal('app=core&module=settings&controller=login&do=form') );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,48 +213,78 @@ class _login extends \IPS\Node\Controller
|
||||
*/
|
||||
protected function enableToggle()
|
||||
{
|
||||
$node = \IPS\Login\LoginAbstract::load( \IPS\Request::i()->id );
|
||||
|
||||
$loginMethod = \IPS\Login\Handler::load( \IPS\Request::i()->id );
|
||||
|
||||
if ( \IPS\Request::i()->status )
|
||||
{
|
||||
if ( method_exists( $node, 'testSettings' ) )
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
$node->testSettings();
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=settings&controller=login&do=form&id={$node->key}" ) );
|
||||
}
|
||||
$loginMethod->testSettings();
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=settings&controller=login&do=form&id={$loginMethod->id}" ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$others = \IPS\Db::i()->select( 'count(*)', 'core_login_handlers', array( 'login_enabled=? and login_key<>?', 1, $node->key ) )->first();
|
||||
|
||||
if( !$others )
|
||||
{
|
||||
\IPS\Output::i()->error( 'login_atleast_one', '1C166/3', 403, '' );
|
||||
}
|
||||
|
||||
/* Allow the login handler to do stuff on-disable */
|
||||
$node->onDisable();
|
||||
$this->_disableCheck( $loginMethod );
|
||||
}
|
||||
|
||||
/* Clear guest page caches */
|
||||
/* Clear caches */
|
||||
unset( \IPS\Data\Store::i()->loginMethods );
|
||||
\IPS\Data\Cache::i()->clearAll();
|
||||
|
||||
/* Toggle */
|
||||
return parent::enableToggle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Settings
|
||||
* Delete
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function settings()
|
||||
protected function delete()
|
||||
{
|
||||
/* Check it's okay */
|
||||
$loginMethod = \IPS\Login\Handler::load( \IPS\Request::i()->id );
|
||||
$this->_disableCheck( $loginMethod );
|
||||
|
||||
/* Do it */
|
||||
parent::delete();
|
||||
|
||||
/* Clear caches */
|
||||
unset( \IPS\Data\Store::i()->loginMethods );
|
||||
\IPS\Data\Cache::i()->clearAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* If a particular method is disabled/deleted - will we still be able to log in?
|
||||
*
|
||||
* @param \IPS\Login\Handler $methodToRemove Handler to be disabled/deleted
|
||||
* @return void
|
||||
*/
|
||||
protected function _disableCheck( \IPS\Login\Handler $methodToRemove )
|
||||
{
|
||||
foreach ( \IPS\Login::methods() as $method )
|
||||
{
|
||||
if ( $method != $methodToRemove and $method->canProcess( \IPS\Member::loggedIn() ) and $method->acp )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
\IPS\Output::i()->error( 'login_handler_cannot_disable', '1C166/5', 403, '' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Login Settings
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function _settings()
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'login_settings' );
|
||||
|
||||
/* Build Form */
|
||||
$form = new \IPS\Helpers\Form();
|
||||
$form->addHeader( 'ipb_bruteforce_attempts' );
|
||||
@@ -142,32 +293,6 @@ class _login extends \IPS\Node\Controller
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'ipb_bruteforce_unlock', \IPS\Settings::i()->ipb_bruteforce_unlock, FALSE, array(), NULL, NULL, NULL, 'ipb_bruteforce_unlock' ) );
|
||||
$form->addHeader( 'login_settings' );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'new_device_email', \IPS\Settings::i()->new_device_email, FALSE ) );
|
||||
|
||||
/* Check if the site works over HTTPS before we allow them to change that */
|
||||
$httpsValue = \IPS\Settings::i()->logins_over_https;
|
||||
$httpsDisabled = FALSE;
|
||||
$toggles = array();
|
||||
if ( mb_substr( \IPS\Settings::i()->base_url, 0, 8 ) === 'https://' )
|
||||
{
|
||||
$httpsValue = TRUE;
|
||||
$httpsDisabled = TRUE;
|
||||
\IPS\Member::loggedIn()->language()->words['logins_over_https_desc'] = \IPS\Member::loggedIn()->language()->addToStack( 'logins_over_https_enabled', FALSE );
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
$response = \IPS\Http\Url::external( 'https://' . mb_substr( \IPS\Settings::i()->base_url, 7 ) )->request()->get();
|
||||
}
|
||||
catch ( \IPS\Http\Request\Exception $e )
|
||||
{
|
||||
$httpsValue = FALSE;
|
||||
$httpsDisabled = TRUE;
|
||||
$toggles[] = 'form_logins_over_https_warning';
|
||||
\IPS\Member::loggedIn()->language()->words['logins_over_https_desc'] = \IPS\Member::loggedIn()->language()->addToStack( 'logins_over_https_disabled', FALSE, array( 'sprintf' => array( $e->getMessage() ) ) );
|
||||
}
|
||||
}
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'logins_over_https', $httpsValue, FALSE, array( 'disabled' => $httpsDisabled, 'togglesOn' => $toggles ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'disable_anonymous', !\IPS\Settings::i()->disable_anonymous, FALSE, array(), NULL, NULL, NULL, 'disable_anonymous' ) );
|
||||
|
||||
/* Save */
|
||||
@@ -189,125 +314,220 @@ class _login extends \IPS\Node\Controller
|
||||
\IPS\Db::i()->update( 'core_tasks', array( 'enabled' => 1 ), "`key`='unlockmembers'" );
|
||||
}
|
||||
|
||||
/* Cache this for the later check */
|
||||
$currentLoginSetting = \IPS\Settings::i()->logins_over_https;
|
||||
|
||||
$form->saveAsSettings( $values );
|
||||
|
||||
/* Reset datastore if https setting has changed */
|
||||
if( $currentLoginSetting != $values['logins_over_https'] )
|
||||
{
|
||||
\IPS\Theme::deleteCompiledCss();
|
||||
\IPS\Data\Store::i()->clearAll();
|
||||
}
|
||||
|
||||
/* Clear guest page caches */
|
||||
\IPS\Data\Cache::i()->clearAll();
|
||||
|
||||
\IPS\Session::i()->log( 'acplogs__login_settings' );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=settings&controller=login' ), 'saved' );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=settings&controller=login&tab=settings' ), 'saved' );
|
||||
}
|
||||
|
||||
/* Display */
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global' )->block( 'login_settings', $form, FALSE );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'login_settings' );
|
||||
\IPS\Output::i()->breadcrumb[] = array( NULL, \IPS\Member::loggedIn()->language()->addToStack( 'login_settings' ) );
|
||||
return (string) $form;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Manually reprocess IPS Connect requests that are queued
|
||||
* HTTPS check
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
protected function httpsCheck()
|
||||
{
|
||||
try
|
||||
{
|
||||
$response = \IPS\Http\Url::external( 'https://' . mb_substr( \IPS\Settings::i()->base_url, 7 ) )->request()->get();
|
||||
\IPS\Output::i()->output = $response;
|
||||
}
|
||||
catch ( \IPS\Http\Request\Exception $e )
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global' )->message( $e->getMessage() ?: '500_error_title', 'error' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registration Settings
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function _registration()
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'registration_settings' );
|
||||
|
||||
/* Build Form */
|
||||
$form = new \IPS\Helpers\Form();
|
||||
$form->addHeader('registration_standard_settings');
|
||||
$form->addMessage('registration_standard_settings_blurb');
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'allow_reg', \IPS\Login::registrationType(), FALSE, array(
|
||||
'options' => array(
|
||||
'normal' => 'allow_reg_normal',
|
||||
'full' => 'allow_reg_full',
|
||||
'redirect' => 'allow_reg_redirect',
|
||||
'disabled' => 'allow_reg_disabled'
|
||||
),
|
||||
'toggles' => array(
|
||||
'full' => array( 'minimum_age', 'use_coppa' ),
|
||||
'redirect' => array( 'allow_reg_target' )
|
||||
),
|
||||
'disabled' => \IPS\Login\Handler::findMethod( 'IPS\Login\Handler\Standard' ) ? array() : array( 'normal', 'full' )
|
||||
) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Url( 'allow_reg_target', \IPS\Settings::i()->allow_reg_target, NULL, array(), function( $val )
|
||||
{
|
||||
if ( !$val and \IPS\Request::i()->allow_red === 'redirect' )
|
||||
{
|
||||
throw new \DomainException('form_required');
|
||||
}
|
||||
}, NULL, NULL, 'allow_reg_target' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'minimum_age', \IPS\Settings::i()->minimum_age, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'any_age' ), NULL, NULL, NULL, 'minimum_age' ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'use_coppa', \IPS\Settings::i()->use_coppa, FALSE, array( 'togglesOn' => array( 'coppa_fax', 'coppa_address' ) ), NULL, NULL, NULL, 'use_coppa' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Tel( 'coppa_fax', \IPS\Settings::i()->coppa_fax, FALSE, array(), NULL, NULL, NULL, 'coppa_fax' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Address( 'coppa_address', \IPS\GeoLocation::buildFromJson( \IPS\Settings::i()->coppa_address ), FALSE, array(), NULL, NULL, NULL, 'coppa_address' ) );
|
||||
$form->addHeader('registration_global_settings');
|
||||
$form->addMessage('registration_global_settings_blurb');
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'reg_auth_type', \IPS\Settings::i()->reg_auth_type, FALSE, array(
|
||||
'options' => array( 'user' => 'reg_auth_type_user', 'admin' => 'reg_auth_type_admin', 'admin_user' => 'reg_auth_type_admin_user', 'none' => 'reg_auth_type_none' ),
|
||||
'toggles' => array( 'user' => array( 'validate_day_prune' ), 'admin_user' => array( 'validate_day_prune' ) )
|
||||
), NULL, NULL, NULL, 'reg_auth_type' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'validate_day_prune', \IPS\Settings::i()->validate_day_prune, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'never' ), NULL, \IPS\Member::loggedIn()->language()->addToStack('after'), \IPS\Member::loggedIn()->language()->addToStack('days'), 'validate_day_prune' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Stack( 'allowed_reg_email', explode( ',', \IPS\Settings::i()->allowed_reg_email ), FALSE, array( 'placeholder' => 'mycompany.com' ), function( $value ) {
|
||||
if( isset( $value[0] ) AND mb_stripos( $value[0], '@' ) )
|
||||
{
|
||||
throw new \DomainException( 'allowed_reg_email_email_detected' );
|
||||
}
|
||||
}, NULL, NULL ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'new_reg_notify', \IPS\Settings::i()->new_reg_notify, FALSE, array(), NULL, NULL, NULL, 'new_reg_notify' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'force_reg_terms', \IPS\Settings::i()->force_reg_terms, FALSE, array( 'options' => array(
|
||||
'0' => 'force_reg_terms_0',
|
||||
'1' => 'force_reg_terms_1',
|
||||
) ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'updates_consent_default', \IPS\Settings::i()->updates_consent_default, FALSE, array(
|
||||
'options' => array( 'enabled' => 'updates_consent_enabled', 'disabled' => 'updates_consent_disabled' ),
|
||||
), NULL, NULL, NULL, 'updates_consent_default' ) );
|
||||
|
||||
/* Save */
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
/* Save */
|
||||
if ( isset( $values['allowed_reg_email'] ) and is_array( $values['allowed_reg_email'] ) )
|
||||
{
|
||||
$values['allowed_reg_email'] = implode( ',', $values['allowed_reg_email'] );
|
||||
}
|
||||
$form->saveAsSettings( $values );
|
||||
\IPS\Session::i()->log( 'acplogs__registration_settings' );
|
||||
|
||||
/* Clear guest page caches */
|
||||
\IPS\Data\Cache::i()->clearAll();
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=settings&controller=login&tab=registration' ), 'saved' );
|
||||
}
|
||||
|
||||
/* Display */
|
||||
return (string) $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Account Management Settings
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function _accountsettings()
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'login_account_management' );
|
||||
|
||||
/* Build Form */
|
||||
$form = new \IPS\Helpers\Form();
|
||||
$form->addHeader( 'security_header_accounts' );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'password_strength_meter', \IPS\Settings::i()->password_strength_meter, FALSE, array( 'togglesOn' => array( 'password_strength_meter_enforce' ) ), NULL, NULL, NULL, 'password_strength_meter' ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'password_strength_meter_enforce', \IPS\Settings::i()->password_strength_meter_enforce, FALSE, array( 'togglesOn' => array( 'password_strength_option' ) ), NULL, NULL, NULL, 'password_strength_meter_enforce' ) );
|
||||
$strengthOptions = array(
|
||||
'3' => 'strength_3',
|
||||
'4' => 'strength_4',
|
||||
'5' => 'strength_5',
|
||||
);
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'password_strength_option', \IPS\Settings::i()->password_strength_option, FALSE, array( 'options' => $strengthOptions ), NULL, NULL, NULL, 'password_strength_option' ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'device_management', \IPS\Settings::i()->device_management, FALSE ) );
|
||||
$form->addHeader('account_management_email_pass');
|
||||
$form->addMessage('account_management_email_pass_blurb');
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'allow_email_changes', \IPS\Settings::i()->allow_email_changes, FALSE, array(
|
||||
'options' => array(
|
||||
'normal' => 'allow_email_changes_normal',
|
||||
'redirect' => 'allow_email_changes_redirect',
|
||||
'disabled' => 'allow_email_changes_disabled',
|
||||
),
|
||||
'toggles' => array(
|
||||
'redirect' => array( 'allow_email_changes_target' )
|
||||
)
|
||||
) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Url( 'allow_email_changes_target', \IPS\Settings::i()->allow_email_changes_target, NULL, array(), function( $val )
|
||||
{
|
||||
if ( !$val and \IPS\Request::i()->allow_email_changes === 'redirect' )
|
||||
{
|
||||
throw new \DomainException('form_required');
|
||||
}
|
||||
}, NULL, NULL, 'allow_email_changes_target' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'allow_password_changes', \IPS\Settings::i()->allow_password_changes, FALSE, array(
|
||||
'options' => array(
|
||||
'normal' => 'allow_password_changes_normal',
|
||||
'redirect' => 'allow_password_changes_redirect',
|
||||
'disabled' => 'allow_password_changes_disabled',
|
||||
),
|
||||
'toggles' => array(
|
||||
'redirect' => array( 'allow_password_changes_target' )
|
||||
)
|
||||
) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Url( 'allow_password_changes_target', \IPS\Settings::i()->allow_password_changes_target, NULL, array(), function( $val )
|
||||
{
|
||||
if ( !$val and \IPS\Request::i()->allow_password_changes === 'redirect' )
|
||||
{
|
||||
throw new \DomainException('form_required');
|
||||
}
|
||||
}, NULL, NULL, 'allow_password_changes_target' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'allow_forgot_password', \IPS\Settings::i()->allow_forgot_password, FALSE, array(
|
||||
'options' => array(
|
||||
'normal' => 'allow_forgot_password_normal',
|
||||
'handler' => 'allow_forgot_password_handler',
|
||||
'redirect' => 'allow_forgot_password_redirect',
|
||||
'disabled' => 'allow_forgot_password_disabled',
|
||||
),
|
||||
'toggles' => array(
|
||||
'redirect' => array( 'allow_forgot_password_target' )
|
||||
)
|
||||
) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Url( 'allow_forgot_password_target', \IPS\Settings::i()->allow_forgot_password_target, NULL, array(), function( $val )
|
||||
{
|
||||
if ( !$val and \IPS\Request::i()->allow_forgot_password === 'redirect' )
|
||||
{
|
||||
throw new \DomainException('form_required');
|
||||
}
|
||||
}, NULL, NULL, 'allow_forgot_password_target' ) );
|
||||
|
||||
/* Save */
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$values['password_strength_meter_enforce'] = $values['password_strength_meter'] ? $values['password_strength_meter_enforce'] : FALSE;
|
||||
|
||||
$form->saveAsSettings( $values );
|
||||
|
||||
\IPS\Session::i()->log( 'acplogs__account_management_settings' );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=settings&controller=login&tab=accountsettings' ), 'saved' );
|
||||
}
|
||||
|
||||
/* Display */
|
||||
return (string) $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force all users to be logged out
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function retryConnect()
|
||||
protected function forceLogout()
|
||||
{
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('try_slave_request_again');
|
||||
\IPS\Db::i()->update( 'core_members_known_devices', array( 'login_key' => NULL ) );
|
||||
\IPS\Db::i()->delete( 'core_sessions' );
|
||||
|
||||
\IPS\Output::i()->output = new \IPS\Helpers\MultipleRedirect(
|
||||
\IPS\Http\Url::internal( "app=core&module=settings&controller=login&do=retryConnect&slave=" . \IPS\Request::i()->slave ),
|
||||
function( $data )
|
||||
{
|
||||
/* On first cycle get data */
|
||||
if ( !is_array( $data ) )
|
||||
{
|
||||
/* Get total number of failures to process for progress bar */
|
||||
$data = array( 'done' => 0, 'total' => count( \IPS\Db::i()->select( 'id', 'core_ipsconnect_queue', array( 'slave_id=?', intval( \IPS\Request::i()->slave ) ) ) ) );
|
||||
}
|
||||
|
||||
/* Get the next request */
|
||||
try
|
||||
{
|
||||
$request = \IPS\Db::i()->select( 'q.*, s.*', array( 'core_ipsconnect_queue', 'q' ), array( 'q.slave_id=?', intval( \IPS\Request::i()->slave ) ), 'q.id asc', array( 0, 1 ) )
|
||||
->join( array( 'core_ipsconnect_slaves', 's' ), "s.slave_id=q.slave_id" )
|
||||
->first();
|
||||
|
||||
/* Try to process request again */
|
||||
try
|
||||
{
|
||||
parse_str( $request['request_url'], $variables );
|
||||
|
||||
$response = \IPS\Http\Url::external( $request['slave_url'] )
|
||||
->setQueryString( $variables )
|
||||
->request()
|
||||
->get();
|
||||
|
||||
if( $response->httpResponseCode !== NULL AND $response->httpResponseCode > 200 )
|
||||
{
|
||||
/* Update fail count */
|
||||
\IPS\Db::i()->update( 'core_ipsconnect_queue', 'fail_count=fail_count+1', array( 'id=?', $request['id'] ) );
|
||||
|
||||
/* Show error message */
|
||||
\IPS\Output::i()->error( \IPS\Member::loggedIn()->language()->addToStack( 'connect_failure_details', FALSE, array( 'sprintf' =>
|
||||
array( \IPS\Member::loggedIn()->language()->addToStack('connect_slavefail_http', FALSE, array( 'sprintf' => array( $response->httpResponseCode ) ) ) )
|
||||
) ), '4C166/1', 503, '' );
|
||||
}
|
||||
|
||||
$response = $response->decodeJson();
|
||||
|
||||
/* If this is a registered slave but the slave is telling us Connect is disabled, remove it */
|
||||
if( isset( $response['status'] ) AND $response['status'] == 'DISABLED' )
|
||||
{
|
||||
\IPS\Db::i()->update( 'core_ipsconnect_slaves', array( 'slave_enabled' => 0 ), array( 'slave_id=?', $request['slave_id'] ) );
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => \IPS\Db::i()->select( 'COUNT(*)', 'core_ipsconnect_slaves', array( 'slave_enabled=?', 1 ) )->first() ), array( 'conf_key=?', 'connect_slaves' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
}
|
||||
else if( !isset( $response['status'] ) OR $response['status'] != 'SUCCESS' )
|
||||
{
|
||||
throw new \RuntimeException( $response['status'] );
|
||||
}
|
||||
|
||||
/* If we are here, request succeeded - remove from queue */
|
||||
\IPS\Db::i()->delete( 'core_ipsconnect_queue', array( 'id=?', $request['id'] ) );
|
||||
}
|
||||
catch( \RuntimeException $e )
|
||||
{
|
||||
/* Update fail count */
|
||||
\IPS\Db::i()->update( 'core_ipsconnect_queue', 'fail_count=fail_count+1', array( 'id=?', $request['id'] ) );
|
||||
|
||||
/* The request failed - show the admin why */
|
||||
\IPS\Output::i()->error( \IPS\Member::loggedIn()->language()->addToStack('connect_failure_details', FALSE, array( 'sprintf' => array( $e->getMessage() ) ) ), '4C166/2', 503, '' );
|
||||
}
|
||||
|
||||
$data['done']++;
|
||||
|
||||
/* Return null to indicate we are done */
|
||||
return array( $data, 'connect_retry_success', round( $data['done'] / $data['total'] ) );
|
||||
}
|
||||
catch( \UnderflowException $e )
|
||||
{
|
||||
\IPS\Session::i()->log( 'acplog__connect_queue_cleared' );
|
||||
|
||||
/* Disable task */
|
||||
\IPS\Db::i()->update( 'core_tasks', array( 'enabled' => 0 ), "`key`='connect'" );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
},
|
||||
function()
|
||||
{
|
||||
/* And redirect back to the dashboard */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=overview&controller=dashboard' ), 'connect_queue_cleared' );
|
||||
}
|
||||
);
|
||||
\IPS\Session::i()->log( 'acplogs__logout_force' );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=settings&controller=login' ), 'logged_out_force' );
|
||||
}
|
||||
}
|
||||
@@ -79,7 +79,7 @@ class _posting extends \IPS\Dispatcher\Controller
|
||||
protected function manage()
|
||||
{
|
||||
/* Work out output */
|
||||
$activeTabContents = call_user_func( array( $this, '_manage'.ucfirst( $this->activeTab ) ) );
|
||||
$activeTabContents = call_user_func( array( $this, '_manage' . mb_ucfirst( $this->activeTab ) ) );
|
||||
|
||||
/* If this is an AJAX request, just return it */
|
||||
if( \IPS\Request::i()->isAjax() )
|
||||
@@ -109,8 +109,8 @@ class _posting extends \IPS\Dispatcher\Controller
|
||||
$form->hiddenValues['rebuildImageProxy'] = \IPS\Request::i()->rebuildImageProxy ?: 0;
|
||||
$form->addHeader('posting_attachments');
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'attach_allowed_types', \IPS\Settings::i()->attach_allowed_types, FALSE, array(
|
||||
'options' => array( 'all' => 'attach_allowed_types_all', 'images' => 'attach_allowed_types_images', 'none' => 'attach_allowed_types_none' ),
|
||||
'toggles' => array( 'all' => array( 'attach_allowed_extensions', 'attachment_resample_size', 'attachment_image_size' ), 'images' => array( 'attachment_resample_size', 'attachment_image_size' ) )
|
||||
'options' => array( 'all' => 'attach_allowed_types_all', 'media' => 'attach_allowed_types_media', 'images' => 'attach_allowed_types_images', 'none' => 'attach_allowed_types_none' ),
|
||||
'toggles' => array( 'all' => array( 'attach_allowed_extensions', 'attachment_resample_size', 'attachment_image_size' ), 'media' => array( 'attachment_resample_size', 'attachment_image_size' ), 'images' => array( 'attachment_resample_size', 'attachment_image_size' ) )
|
||||
) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'attach_allowed_extensions', \IPS\Settings::i()->attach_allowed_extensions ? explode( ',', \IPS\Settings::i()->attach_allowed_extensions ) : NULL, FALSE, array( 'nullLang' => 'no_restriction', 'autocomplete' => array( 'freeChoice' => TRUE, 'source' => array( 'doc', 'docx', 'log', 'msg', 'odt', 'pages', 'rtf', 'tex', 'txt', 'wpd', 'wps', 'csv', 'dat', 'gbr', 'ged', 'key', 'keychain', 'pps', 'ppt', 'pptx', 'sdf', 'tar', 'tax2012', 'tax2014', 'vcf', 'xml', 'aif', 'iff', 'm3u', 'm4a', 'mid', 'mp3', 'mpa', 'ra', 'wav', 'wma', '3g2', '3gp', 'asf', 'asx', 'avi', 'flv', 'm4v', 'mov', 'mp4', 'mpg', 'rm', 'srt', 'swf', 'vob', 'wmv', '3dm', '3ds', 'max', 'obj', 'bmp', 'dds', 'gif', 'jpg', 'png', 'psd', 'pspimage', 'tga', 'thm', 'tif', 'tiff', 'yuv', 'ai', 'eps', 'ps', 'svg', 'indd', 'pct', 'pdf', 'xlr', 'xls', 'xlsx', 'accdb', 'db', 'dbf', 'mdb', 'pdb', 'sql', 'apk', 'app', 'bat', 'cgi', 'com', 'exe', 'gadget', 'jar', 'pif', 'vb', 'wsf', 'dem', 'gam', 'nes', 'rom', 'sav', 'dwg', 'dxf', 'gpx', 'kml', 'kmz', 'asp', 'aspx', 'cer', 'cfm', 'csr', 'css', 'htm', 'html', 'js', 'jsp', 'php', 'rss', 'xhtml', 'crx', 'plugin', 'fnt', 'fon', 'otf', 'ttf', 'cab', 'cpl', 'cur', 'deskthemepack', 'dll', 'dmp', 'drv', 'icns', 'ico', 'lnk', 'sys', 'cfg', 'ini', 'prf', 'hqx', 'mim', 'uue', '7z', 'cbr', 'deb', 'gz', 'pkg', 'rar', 'rpm', 'sitx', 'tar.gz', 'zip', 'zipx', 'bin', 'cue', 'dmg', 'iso', 'mdf', 'toast', 'vcd', 'c', 'class', 'cpp', 'cs', 'dtd', 'fla', 'h', 'java', 'lua', 'm', 'pl', 'py', 'sh', 'sln', 'swift', 'vcxproj', 'xcodeproj', 'bak', 'tmp', 'crdownload', 'ics', 'msi', 'part', 'torrent' ) ) ), NULL, NULL, NULL, 'attach_allowed_extensions' ) );
|
||||
$form->addHeader('posting_images');
|
||||
@@ -170,7 +170,7 @@ class _posting extends \IPS\Dispatcher\Controller
|
||||
) ) );
|
||||
}
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'dellog_retention_period', \IPS\Settings::i()->dellog_retention_period, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'immediately' ), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack('dellog_days_after_deleted') ) );
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'dellog_retention_period', \IPS\Settings::i()->dellog_retention_period, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'immediately', 'max' => PHP_INT_MAX ), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack('dellog_days_after_deleted') ) );
|
||||
|
||||
/* Save values */
|
||||
if ( $values = $form->values() )
|
||||
@@ -191,7 +191,7 @@ class _posting extends \IPS\Dispatcher\Controller
|
||||
if( $values['rebuildImageProxy'] )
|
||||
{
|
||||
/* Remove any existing rebuilds */
|
||||
\IPS\Db::i()->delete( 'core_queue', array( '`key`=? OR `key`=?', 'RebuildImageProxy', 'RebuildImageProxyNonContent' ) );
|
||||
\IPS\Db::i()->delete( 'core_queue', \IPS\Db::i()->in( '`key`', array( 'RebuildImageProxy', 'RebuildImageProxyNonContent', 'DeleteImageProxyFiles' ) ) );
|
||||
|
||||
/* Unset task datastore */
|
||||
unset( \IPS\Data\Store::i()->currentImageProxyRebuild );
|
||||
@@ -199,21 +199,32 @@ class _posting extends \IPS\Dispatcher\Controller
|
||||
$enableDisable = $values['remote_image_proxy'] ? TRUE : FALSE;
|
||||
foreach ( \IPS\Content::routedClasses( FALSE, TRUE ) as $class )
|
||||
{
|
||||
try
|
||||
if( isset( $class::$databaseColumnMap['content'] ) )
|
||||
{
|
||||
\IPS\Task::queue( 'core', 'RebuildImageProxy', array( 'class' => $class, 'status' => $enableDisable ), 5 );
|
||||
try
|
||||
{
|
||||
\IPS\Task::queue( 'core', 'RebuildImageProxy', array( 'class' => $class, 'status' => $enableDisable ), 4 );
|
||||
}
|
||||
catch( \OutOfRangeException $ex ) { }
|
||||
}
|
||||
catch( \OutOfRangeException $ex ) { }
|
||||
}
|
||||
|
||||
foreach( \IPS\Application::allExtensions( 'core', 'EditorLocations', FALSE, NULL, NULL, TRUE, TRUE ) as $_key => $extension )
|
||||
{
|
||||
if( method_exists( $extension, 'rebuildImageProxy' ) )
|
||||
{
|
||||
\IPS\Task::queue( 'core', 'RebuildImageProxyNonContent', array( 'extension' => $_key, 'status' => $enableDisable ), 5 );
|
||||
\IPS\Task::queue( 'core', 'RebuildImageProxyNonContent', array( 'extension' => $_key, 'status' => $enableDisable ), 4 );
|
||||
}
|
||||
}
|
||||
|
||||
/* If we're disabling the image proxy, also delete the files */
|
||||
if( !$enableDisable )
|
||||
{
|
||||
\IPS\Task::queue( 'core', 'DeleteImageProxyFiles', array( 'status' => $enableDisable ), 5 );
|
||||
}
|
||||
}
|
||||
|
||||
unset( $values['rebuildImageProxy'] );
|
||||
|
||||
$form->saveAsSettings( $values );
|
||||
|
||||
@@ -417,14 +428,26 @@ class _posting extends \IPS\Dispatcher\Controller
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'max_poll_choices', \IPS\Settings::i()->max_poll_choices ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'poll_allow_public', \IPS\Settings::i()->poll_allow_public ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'ipb_poll_only', \IPS\Settings::i()->ipb_poll_only ) );
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'startpoll_cutoff', \IPS\Settings::i()->startpoll_cutoff, FALSE, array( 'unlimited' => -1, 'unlimitedLang' => 'always' ), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack('hours') ) );
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'allow_poll_creation_after', ( \IPS\Settings::i()->startpoll_cutoff ? TRUE : FALSE ), FALSE, array( 'togglesOn' => array( 'startpoll_cutoff' ) ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'startpoll_cutoff', \IPS\Settings::i()->startpoll_cutoff, FALSE, array( 'unlimited' => -1, 'unlimitedLang' => 'always', 'max' => 43800 ), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack('hours'), 'startpoll_cutoff' ) ); #max is roughly 5 years
|
||||
|
||||
$form->addHeader('poll_voting');
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'allow_creator_vote', \IPS\Settings::i()->allow_creator_vote ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'poll_allow_vdelete', \IPS\Settings::i()->poll_allow_vdelete, FALSE ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'allow_result_view', \IPS\Settings::i()->allow_result_view, FALSE, array(), NULL, NULL, NULL, 'allow_result_view' ) );
|
||||
|
||||
if ( $form->saveAsSettings() )
|
||||
if ( $values = $form->values( TRUE ) )
|
||||
{
|
||||
if ( ! $values['allow_poll_creation_after'] )
|
||||
{
|
||||
$values['startpoll_cutoff'] = 0;
|
||||
}
|
||||
|
||||
unset( $values['allow_poll_creation_after'] );
|
||||
|
||||
$form->saveAsSettings( $values );
|
||||
|
||||
/* Clear guest page caches */
|
||||
\IPS\Data\Cache::i()->clearAll();
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ class _terms extends \IPS\Dispatcher\Controller
|
||||
|
||||
$form->addHeader( 'guest_terms_options' );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'guest_terms_bar', \IPS\Settings::i()->guest_terms_bar, FALSE, array( 'togglesOn' => array( 'guest_terms_bar_text' ) ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Translatable( 'guest_terms_bar_text', NULL, FALSE, array( 'app' => 'core', 'key' => 'guest_terms_bar_text_value', 'sprintf' => array( '{terms}', '{privacy}', '{guidelines}' ) ), NULL, NULL, NULL, 'guest_terms_bar_text' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Translatable( 'guest_terms_bar_text', NULL, FALSE, array( 'app' => 'core', 'key' => 'guest_terms_bar_text_value', 'sprintf' => array( '{terms}', '{privacy}', '{guidelines}', '{cookies}' ) ), NULL, NULL, NULL, 'guest_terms_bar_text' ) );
|
||||
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
@@ -93,7 +93,7 @@ class _terms extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
foreach( $values[ $k ] AS $lang_id => $text )
|
||||
{
|
||||
$values[ $k ][ $lang_id ] = str_replace( array( '{terms}', '{privacy}', '{guidelines}' ), array( '%1$s', '%2$s', '%3$s' ), $text );
|
||||
$values[ $k ][ $lang_id ] = str_replace( array( '{terms}', '{privacy}', '{guidelines}', '{cookies}' ), array( '%1$s', '%2$s', '%3$s', '%4$s' ), $text );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,29 +46,40 @@ class _admin extends \IPS\Dispatcher\Controller
|
||||
$table = new \IPS\Helpers\Table\Db( 'core_admin_permission_rows', \IPS\Http\Url::internal( 'app=core&module=staff&controller=admin' ) );
|
||||
|
||||
/* Columns */
|
||||
$table->selects = array( 'row_perm_cache', 'row_updated', 'row_id', 'row_id_type' );
|
||||
$table->langPrefix = 'acprestrictions_';
|
||||
$table->joins = array(
|
||||
array( 'select' => "IF(core_admin_permission_rows.row_id_type= 'group', w.word_custom, m.name) as name", 'from' => array( 'core_members', 'm' ), 'where' => "m.member_id=core_admin_permission_rows.row_id AND core_admin_permission_rows.row_id_type='member'" ),
|
||||
array( 'from' => array( 'core_sys_lang_words', 'w' ), 'where' => "w.word_key=CONCAT( 'core_group_', core_admin_permission_rows.row_id ) AND core_admin_permission_rows.row_id_type='group' AND w.lang_id=" . \IPS\Member::loggedIn()->language()->id )
|
||||
);
|
||||
$table->include = array( 'row_id_type', 'row_id', 'row_updated' );
|
||||
$table->include = array( 'name', 'row_updated', 'row_perm_cache' );
|
||||
$table->parsers = array(
|
||||
'row_id_type' => function( $val, $row )
|
||||
'name' => function( $val, $row )
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate( 'global' )->shortMessage( $val, array( 'ipsBadge', 'ipsBadge_neutral' ) );
|
||||
},
|
||||
'row_id' => function( $val, $row )
|
||||
{
|
||||
return $row['row_id_type'] === 'group' ? \IPS\Member\Group::load( $row['row_id'] )->formattedName : htmlentities( $row['name'], \IPS\HTMLENTITIES, 'UTF-8', FALSE );
|
||||
$return = \IPS\Theme::i()->getTemplate( 'global' )->shortMessage( $row['row_id_type'], array( 'ipsBadge', 'ipsBadge_neutral', 'ipsBadge_label' ) );
|
||||
try
|
||||
{
|
||||
$name = empty( $row['name'] ) ? \IPS\Member::loggedIn()->language()->addToStack('deleted_member') : htmlentities( $row['name'], ENT_DISALLOWED, 'UTF-8', FALSE );
|
||||
$return .= ( $row['row_id_type'] === 'group' ) ? \IPS\Member\Group::load( $row['row_id'] )->formattedName : $name;
|
||||
}
|
||||
catch( \OutOfRangeException $e )
|
||||
{
|
||||
$return .= \IPS\Member::loggedIn()->language()->addToStack('deleted_group');
|
||||
}
|
||||
return $return;
|
||||
},
|
||||
'row_updated' => function( $val )
|
||||
{
|
||||
return ( $val ) ? \IPS\DateTime::ts( $val )->localeDate() : \IPS\Member::loggedIn()->language()->addToStack('never');
|
||||
},
|
||||
'row_perm_cache' => function( $val )
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate( 'members' )->restrictionsLabel( $val );
|
||||
}
|
||||
);
|
||||
$table->mainColumn = 'name';
|
||||
$table->quickSearch = array( array( 'name', 'word_custom' ), 'row_id' );
|
||||
$table->classes = array( 'row_id_type' => 'icon' );
|
||||
$table->quickSearch = array( array( 'name', 'word_custom' ), 'name' );
|
||||
$table->noSort = array( 'row_perm_cache' );
|
||||
|
||||
/* Sorting */
|
||||
$table->sortBy = $table->sortBy ?: 'row_updated';
|
||||
@@ -160,11 +171,20 @@ class _admin extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
\IPS\Output::i()->sidebar['actions']['loginLogs'] = array(
|
||||
'title' => 'adminloginlogs',
|
||||
'icon' => 'key',
|
||||
'icon' => 'search',
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=staff&controller=admin&do=loginLogs' ),
|
||||
);
|
||||
}
|
||||
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'members' ) )
|
||||
{
|
||||
\IPS\Output::i()->sidebar['actions']['list_admins'] = array(
|
||||
'icon' => 'search',
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=members&controller=members&filter=members_filter_administrators' ),
|
||||
'title' => 'security_list_admins',
|
||||
);
|
||||
}
|
||||
|
||||
/* Display */
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('acprestrictions');
|
||||
\IPS\Output::i()->output = (string) $table;
|
||||
@@ -243,7 +263,7 @@ class _admin extends \IPS\Dispatcher\Controller
|
||||
|
||||
unset( \IPS\Data\Store::i()->administrators );
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=staff&controller=admin&do=edit&id={$current['row_id']}&type={$current['row_id_type']}" ) );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=staff&controller=admin" ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,7 +278,8 @@ class _admin extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function edit()
|
||||
{
|
||||
try {
|
||||
try
|
||||
{
|
||||
/* Get record */
|
||||
$current = \IPS\Db::i()->select( '*', 'core_admin_permission_rows', array( "row_id=? AND row_id_type=?", intval( \IPS\Request::i()->id ), \IPS\Request::i()->type ) )->first();
|
||||
}
|
||||
@@ -311,24 +332,7 @@ class _admin extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Warning if they have all permissions */
|
||||
if ( $current['row_perm_cache'] === '*' )
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->message( 'admin_allperm_warning', 'warning' );
|
||||
}
|
||||
/* Or a button to give all */
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->sidebar['actions'] = array(
|
||||
'all' => array(
|
||||
'title' => 'moderators_allperm',
|
||||
'icon' => 'check-circle',
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=staff&controller=admin&do=allperms&id=' ) . $current['row_id'] . '&type=' . $current['row_id_type'],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/* Display */
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'admin_members.js', 'core', 'admin' ) );
|
||||
\IPS\Output::i()->title = $current['row_id_type'] === 'group' ? \IPS\Member\Group::load( $current['row_id'] )->name : \IPS\Member::load( $current['row_id'] )->name;
|
||||
@@ -349,8 +353,10 @@ class _admin extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->error( 'node_error', '2C113/2', 404, '' );
|
||||
}
|
||||
|
||||
$permissions = ( \IPS\Request::i()->admin_use_restrictions == 'no' ) ? '*' : json_encode( ( is_array( \IPS\Request::i()->r ) ) ? \IPS\Request::i()->r : array() );
|
||||
|
||||
/* Save */
|
||||
\IPS\Db::i()->update( 'core_admin_permission_rows', array( 'row_perm_cache' => json_encode( ( is_array( \IPS\Request::i()->r ) ) ? \IPS\Request::i()->r : array() ), 'row_updated' => time() ), array( "row_id=? AND row_id_type=?", intval( \IPS\Request::i()->id ), \IPS\Request::i()->type ) );
|
||||
\IPS\Db::i()->update( 'core_admin_permission_rows', array( 'row_perm_cache' => $permissions, 'row_updated' => time() ), array( "row_id=? AND row_id_type=?", intval( \IPS\Request::i()->id ), \IPS\Request::i()->type ) );
|
||||
|
||||
unset( \IPS\Data\Store::i()->administrators );
|
||||
|
||||
@@ -360,32 +366,7 @@ class _admin extends \IPS\Dispatcher\Controller
|
||||
/* Boink */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=staff&controller=admin' ), 'saved' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Give All Permissions
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function allperms()
|
||||
{
|
||||
/* Load */
|
||||
$current = \IPS\Db::i()->select( '*', 'core_admin_permission_rows', array( "row_id=? AND row_id_type=?", intval( \IPS\Request::i()->id ), \IPS\Request::i()->type ) )->first();
|
||||
if ( !$current )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C113/5', 404, '' );
|
||||
}
|
||||
|
||||
/* Set */
|
||||
\IPS\Db::i()->update( 'core_admin_permission_rows', array( 'row_perm_cache' => '*', 'row_updated' => time() ), array( array( "row_id=? AND row_id_type=?", $current['row_id'], $current['row_id_type'] ) ) );
|
||||
|
||||
unset( \IPS\Data\Store::i()->administrators );
|
||||
|
||||
\IPS\Session::i()->log( 'acplog__acpr_edited', array( ( $current['row_id_type'] == 'group' ? \IPS\Member\Group::load( $current['row_id'] )->name : \IPS\Member::load( $current['row_id'] )->name ) => FALSE ) );
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=staff&controller=admin&do=edit&id=' . $current['row_id'] . '&type=' . $current['row_id_type'] ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete
|
||||
*
|
||||
@@ -407,7 +388,32 @@ class _admin extends \IPS\Dispatcher\Controller
|
||||
/* Make sure the user confirmed the deletion */
|
||||
\IPS\Request::i()->confirmedDelete();
|
||||
|
||||
\IPS\Session::i()->log( 'acplog__acpr_deleted', array( ( $current['row_id_type'] == 'group' ? \IPS\Member\Group::load( $current['row_id'] )->name : \IPS\Member::load( $current['row_id'] )->name ) => FALSE ) );
|
||||
if( $current['row_id_type'] == 'group' )
|
||||
{
|
||||
try
|
||||
{
|
||||
$name = \IPS\Member\Group::load( $current['row_id'] )->name;
|
||||
}
|
||||
catch( \OutOfRangeException $e )
|
||||
{
|
||||
$name = \IPS\Member::loggedIn()->language()->get('deleted_group');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$member = \IPS\Member::load( $current['row_id'] );
|
||||
|
||||
if( $member->member_id )
|
||||
{
|
||||
$name = $member->name;
|
||||
}
|
||||
else
|
||||
{
|
||||
$name = \IPS\Member::loggedIn()->language()->get('deleted_member');
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Session::i()->log( 'acplog__acpr_deleted', array( $name => FALSE ) );
|
||||
\IPS\Db::i()->delete( 'core_admin_permission_rows', array( 'row_id=? AND row_id_type=?', intval( \IPS\Request::i()->id ), \IPS\Request::i()->type ) );
|
||||
unset ( \IPS\Data\Store::i()->administrators );
|
||||
|
||||
@@ -434,11 +440,11 @@ class _admin extends \IPS\Dispatcher\Controller
|
||||
$member = \IPS\Member::load( $val );
|
||||
if ( $member->member_id )
|
||||
{
|
||||
return htmlentities( \IPS\Member::load( $val )->name, \IPS\HTMLENTITIES, 'UTF-8', FALSE );
|
||||
return htmlentities( \IPS\Member::load( $val )->name, ENT_DISALLOWED, 'UTF-8', FALSE );
|
||||
}
|
||||
else if ( $row['member_name'] != '' )
|
||||
{
|
||||
return htmlentities( $row['member_name'], \IPS\HTMLENTITIES, 'UTF-8', FALSE );
|
||||
return htmlentities( $row['member_name'], ENT_DISALLOWED, 'UTF-8', FALSE );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -30,7 +30,9 @@ class _moderators extends \IPS\Dispatcher\Controller
|
||||
public function execute()
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'moderators_manage' );
|
||||
parent::execute();
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'members/restrictions.css', 'core', 'admin' ) );
|
||||
|
||||
return parent::execute();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -42,31 +44,42 @@ class _moderators extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/* Create the table */
|
||||
$table = new \IPS\Helpers\Table\Db( 'core_moderators', \IPS\Http\Url::internal( 'app=core&module=staff&controller=moderators' ) );
|
||||
|
||||
|
||||
/* Columns */
|
||||
$table->langPrefix = 'moderators_';
|
||||
$table->langPrefix = 'moderators_';
|
||||
$table->selects = array( 'perms', 'id', 'type', 'updated' );
|
||||
$table->joins = array(
|
||||
array( 'select' => "IF(core_moderators.type= 'g', w.word_custom, m.name) as name", 'from' => array( 'core_members', 'm' ), 'where' => "m.member_id=core_moderators.id AND core_moderators.type='m'" ),
|
||||
array( 'from' => array( 'core_sys_lang_words', 'w' ), 'where' => "w.word_key=CONCAT( 'core_group_', core_moderators.id ) AND core_moderators.type='g' AND w.lang_id=" . \IPS\Member::loggedIn()->language()->id )
|
||||
);
|
||||
$table->include = array( 'type', 'id', 'updated' );
|
||||
$table->include = array( 'name', 'updated', 'perms' );
|
||||
$table->parsers = array(
|
||||
'type' => function( $val, $row )
|
||||
'name' => function( $val, $row )
|
||||
{
|
||||
return "<i class='fa fa-" . ( ( $val === 'm' ) ? 'user' : 'group' ) . "' data-ipstooltip _title=' " . ( ( $val === 'm' ) ? \IPS\Member::loggedIn()->language()->addToStack('acprestrictions_member') : \IPS\Member::loggedIn()->language()->addToStack('acprestrictions_group') ) . "'></i>";
|
||||
},
|
||||
'id' => function( $val, $row )
|
||||
{
|
||||
return $row['type'] === 'g' ? \IPS\Member\Group::load( $row['id'] )->formattedName : htmlentities( $row['name'], \IPS\HTMLENTITIES, 'UTF-8', FALSE );
|
||||
$return = \IPS\Theme::i()->getTemplate( 'global' )->shortMessage( $row['type'] === 'g' ? 'group' : 'member', array( 'ipsBadge', 'ipsBadge_neutral', 'ipsBadge_label' ) );
|
||||
try
|
||||
{
|
||||
$name = empty( $row['name'] ) ? \IPS\Member::loggedIn()->language()->addToStack('deleted_member') : htmlentities( $row['name'], ENT_DISALLOWED, 'UTF-8', FALSE );
|
||||
$return .= ( $row['type'] === 'g' ) ? \IPS\Member\Group::load( $row['id'] )->formattedName : $name;
|
||||
}
|
||||
catch( \OutOfRangeException $e )
|
||||
{
|
||||
$return .= \IPS\Member::loggedIn()->language()->addToStack('deleted_group');
|
||||
}
|
||||
return $return;
|
||||
},
|
||||
'updated' => function( $val )
|
||||
{
|
||||
return ( $val ) ? \IPS\DateTime::ts( $val )->localeDate() : \IPS\Member::loggedIn()->language()->addToStack('never');
|
||||
},
|
||||
'perms' => function( $val )
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate( 'members' )->restrictionsLabel( $val );
|
||||
}
|
||||
);
|
||||
$table->mainColumn = 'name';
|
||||
$table->quickSearch = array( array( 'name', 'word_custom' ), 'id' );
|
||||
$table->classes = array( 'type' => 'icon' );
|
||||
$table->quickSearch = array( array( 'name', 'word_custom' ), 'name' );
|
||||
$table->noSort = array( 'perms' );
|
||||
|
||||
/* Sorting */
|
||||
$table->sortBy = $table->sortBy ?: 'updated';
|
||||
@@ -212,7 +225,7 @@ class _moderators extends \IPS\Dispatcher\Controller
|
||||
unset (\IPS\Data\Store::i()->moderators);
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=staff&controller=moderators&do=edit&id={$current['id']}&type={$current['type']}" ) );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=staff&controller=moderators" ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,6 +298,12 @@ class _moderators extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Build */
|
||||
$form = new \IPS\Helpers\Form;
|
||||
|
||||
/* Add the restricted/unrestricted option first */
|
||||
$form->add(
|
||||
new \IPS\Helpers\Form\Radio( 'mod_use_restrictions', ( $currentPermissions === '*' ) ? 'no' : 'yes', TRUE, array( 'options' => array( 'no' => 'mod_all_permissions', 'yes' => 'mod_restricted' ), 'toggles' => array( 'yes' => array( 'permission_form_wrapper' ) ) ), NULL, NULL, NULL, 'use_restrictions_id' )
|
||||
);
|
||||
|
||||
$extensions = array();
|
||||
foreach ( \IPS\Application::allExtensions( 'core', 'ModeratorPermissions', FALSE, 'core' ) as $k => $ext )
|
||||
{
|
||||
@@ -373,115 +392,84 @@ class _moderators extends \IPS\Dispatcher\Controller
|
||||
/* Handle submissions */
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
foreach ( $values as $k => $v )
|
||||
if( $values['mod_use_restrictions'] == 'no' )
|
||||
{
|
||||
/* For node fields, if the value is 0 translate it to -1 so mod permissions can merge properly */
|
||||
if( in_array( $k, $nodeFields ) )
|
||||
{
|
||||
/* If nothing is checked we have '', but if 'all' is checked then the value is 0 */
|
||||
if( $v === 0 )
|
||||
{
|
||||
$v = -1;
|
||||
$values[ $k ] = $v;
|
||||
}
|
||||
}
|
||||
$permissions = '*';
|
||||
|
||||
if ( is_array( $v ) )
|
||||
{
|
||||
foreach ( $v as $l => $w )
|
||||
{
|
||||
if ( $w instanceof \IPS\Node\Model )
|
||||
{
|
||||
$values[ $k ][ $l ] = $w->_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $currentPermissions == '*' )
|
||||
{
|
||||
$changed = $values;
|
||||
$changed = '*';
|
||||
}
|
||||
else
|
||||
{
|
||||
$changed = array();
|
||||
unset( $values['mod_use_restrictions'] );
|
||||
|
||||
foreach ( $values as $k => $v )
|
||||
{
|
||||
if ( !isset( $currentPermissions[ $k ] ) or $currentPermissions[ $k ] != $v )
|
||||
/* For node fields, if the value is 0 translate it to -1 so mod permissions can merge properly */
|
||||
if( in_array( $k, $nodeFields ) )
|
||||
{
|
||||
$changed[ $k ] = $v;
|
||||
/* If nothing is checked we have '', but if 'all' is checked then the value is 0 */
|
||||
if( $v === 0 )
|
||||
{
|
||||
$v = -1;
|
||||
$values[ $k ] = $v;
|
||||
}
|
||||
}
|
||||
|
||||
if ( is_array( $v ) )
|
||||
{
|
||||
foreach ( $v as $l => $w )
|
||||
{
|
||||
if ( $w instanceof \IPS\Node\Model )
|
||||
{
|
||||
$values[ $k ][ $l ] = $w->_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $currentPermissions == '*' )
|
||||
{
|
||||
$changed = $values;
|
||||
}
|
||||
else
|
||||
{
|
||||
$changed = array();
|
||||
foreach ( $values as $k => $v )
|
||||
{
|
||||
if ( !isset( $currentPermissions[ $k ] ) or $currentPermissions[ $k ] != $v )
|
||||
{
|
||||
$changed[ $k ] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$permissions = json_encode( $values );
|
||||
}
|
||||
|
||||
\IPS\Db::i()->update( 'core_moderators', array( 'perms' => json_encode( $values ), 'updated' => time() ), array( array( "id=? AND type=?", $current['id'], $current['type'] ) ) );
|
||||
foreach ( \IPS\Application::allExtensions( 'core', 'ModeratorPermissions', FALSE ) as $k => $ext )
|
||||
\IPS\Db::i()->update( 'core_moderators', array( 'perms' => $permissions, 'updated' => time() ), array( array( "id=? AND type=?", $current['id'], $current['type'] ) ) );
|
||||
|
||||
if( !( $currentPermissions == '*' AND $changed == '*' ) )
|
||||
{
|
||||
$ext->onChange( $current, $changed );
|
||||
foreach ( \IPS\Application::allExtensions( 'core', 'ModeratorPermissions', FALSE ) as $k => $ext )
|
||||
{
|
||||
$ext->onChange( $current, $changed );
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Session::i()->log( 'acplog__moderator_edited', array( ( $current['type'] == 'g' ? \IPS\Member::loggedIn()->language()->get( "core_group_{$current['id']}" ) : \IPS\Member::load( $current['id'] )->name ) => FALSE ) );
|
||||
$currentPermissions = $values;
|
||||
|
||||
unset (\IPS\Data\Store::i()->moderators);
|
||||
unset( \IPS\Data\Store::i()->moderators );
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=staff&controller=moderators' ), 'saved' );
|
||||
}
|
||||
|
||||
/* Warning if they have all permissions */
|
||||
if ( $currentPermissions === '*' )
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->message( 'moderators_allperm_warning', 'warning' );
|
||||
}
|
||||
/* Or a button to give all */
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->sidebar['actions'] = array(
|
||||
'all' => array(
|
||||
'title' => 'moderators_allperm',
|
||||
'icon' => 'asterisk',
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=staff&controller=moderators&do=allperms&id=' ) . $current['id'] . '&type=' . $current['type'],
|
||||
'data' => array( 'confirm' => '' )
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/* Display */
|
||||
\IPS\Output::i()->title = $_name;
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'admin_members.js', 'core', 'admin' ) );
|
||||
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'members' )->moderatorPermissions( $_name, $form );
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'admin_members.js', 'core', 'admin' ) );
|
||||
\IPS\Output::i()->output .= $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'members' ) ), 'moderatorPermissions' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Give All Permissions
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function allperms()
|
||||
{
|
||||
/* Load */
|
||||
$current = \IPS\Db::i()->select( '*', 'core_moderators', array( "id=? AND type=?", intval( \IPS\Request::i()->id ), \IPS\Request::i()->type ) )->first();
|
||||
if ( !$current )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C118/3', 404, '' );
|
||||
}
|
||||
|
||||
/* Set */
|
||||
\IPS\Db::i()->update( 'core_moderators', array( 'perms' => '*', 'updated' => time() ), array( array( "id=? AND type=?", $current['id'], $current['type'] ) ) );
|
||||
foreach ( \IPS\Application::allExtensions( 'core', 'ModeratorPermissions', FALSE ) as $k => $ext )
|
||||
{
|
||||
$ext->onChange( $current, '*' );
|
||||
}
|
||||
|
||||
unset ( \IPS\Data\Store::i()->moderators );
|
||||
|
||||
/* Log and redirect */
|
||||
\IPS\Session::i()->log( 'acplog__moderator_edited', array( ( $current['type'] == 'g' ? \IPS\Member::loggedIn()->language()->get( "core_group_{$current['id']}" ) : \IPS\Member::load( $current['id'] )->name ) => FALSE ) );
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=staff&controller=moderators&do=edit&id=' . $current['id'] . '&type=' . $current['type'] ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete
|
||||
*
|
||||
@@ -546,11 +534,11 @@ class _moderators extends \IPS\Dispatcher\Controller
|
||||
$member = \IPS\Member::load( $val );
|
||||
if ( $member->member_id )
|
||||
{
|
||||
return htmlentities( \IPS\Member::load( $val )->name, \IPS\HTMLENTITIES, 'UTF-8', FALSE );
|
||||
return htmlentities( \IPS\Member::load( $val )->name, ENT_DISALLOWED, 'UTF-8', FALSE );
|
||||
}
|
||||
else if ( $row['member_name'] != '' )
|
||||
{
|
||||
return htmlentities( $row['member_name'], \IPS\HTMLENTITIES, 'UTF-8', FALSE );
|
||||
return htmlentities( $row['member_name'], ENT_DISALLOWED, 'UTF-8', FALSE );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Device usage
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 10 Jan 2018
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\admin\stats;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Device usage
|
||||
*/
|
||||
class _deviceusage extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'deviceusage_manage' );
|
||||
parent::execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Device usage chart
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
{
|
||||
/* Show button to adjust settings */
|
||||
\IPS\Output::i()->sidebar['actions']['settings'] = array(
|
||||
'icon' => 'cog',
|
||||
'title' => 'prunesettings',
|
||||
'link' => \IPS\Http\Url::internal( 'app=core&module=stats&controller=deviceusage&do=settings' ),
|
||||
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('prunesettings') )
|
||||
);
|
||||
|
||||
/* Determine minimum date */
|
||||
$minimumDate = NULL;
|
||||
|
||||
if( \IPS\Settings::i()->stats_device_usage_prune )
|
||||
{
|
||||
$minimumDate = \IPS\DateTime::create()->sub( new \DateInterval( 'P' . \IPS\Settings::i()->stats_device_usage_prune . 'D' ) );
|
||||
}
|
||||
|
||||
/* We can't retrieve any stats prior to the new tracking being implemented */
|
||||
try
|
||||
{
|
||||
$oldestLog = \IPS\Db::i()->select( 'MIN(time)', 'core_statistics', array( 'type=?', 'online_users' ) )->first();
|
||||
|
||||
if( !$minimumDate OR $oldestLog < $minimumDate->getTimestamp() )
|
||||
{
|
||||
$minimumDate = \IPS\DateTime::ts( $oldestLog );
|
||||
}
|
||||
}
|
||||
catch( \OutOfRangeException $e )
|
||||
{
|
||||
/* We have nothing tracked, set minimum date to today */
|
||||
$minimumDate = \IPS\DateTime::create();
|
||||
}
|
||||
|
||||
$chart = new \IPS\Helpers\Chart\Database( \IPS\Http\Url::internal( 'app=core&module=stats&controller=deviceusage' ), 'core_statistics', 'time', '', array(
|
||||
'isStacked' => FALSE,
|
||||
'backgroundColor' => '#ffffff',
|
||||
'colors' => array( '#10967e', '#ea7963', '#de6470', '#6b9dde' ),
|
||||
'hAxis' => array( 'gridlines' => array( 'color' => '#f5f5f5' ) ),
|
||||
'lineWidth' => 1,
|
||||
'areaOpacity' => 0.4
|
||||
), 'AreaChart', 'hourly' );
|
||||
|
||||
$chart->where[] = array( 'type=?', 'devices' );
|
||||
$chart->title = \IPS\Member::loggedIn()->language()->addToStack('stats_deviceusage_title');
|
||||
$chart->availableTypes = array( 'AreaChart', 'ColumnChart', 'BarChart' );
|
||||
$chart->enableHourly = TRUE;
|
||||
|
||||
$chart->addSeries( \IPS\Member::loggedIn()->language()->addToStack('stats_devices_mobiles'), 'number', 'SUM(value_1)', TRUE );
|
||||
$chart->addSeries( \IPS\Member::loggedIn()->language()->addToStack('stats_devices_tablets'), 'number', 'SUM(value_2)', TRUE );
|
||||
$chart->addSeries( \IPS\Member::loggedIn()->language()->addToStack('stats_devices_consoles'), 'number', 'SUM(value_3)', TRUE );
|
||||
$chart->addSeries( \IPS\Member::loggedIn()->language()->addToStack('stats_devices_desktops'), 'number', 'SUM(value_4)', TRUE );
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__core_stats_deviceusage');
|
||||
\IPS\Output::i()->output = (string) $chart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prune Settings
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function settings()
|
||||
{
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'stats_device_usage_prune', \IPS\Settings::i()->stats_device_usage_prune, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'never' ), NULL, \IPS\Member::loggedIn()->language()->addToStack('after'), \IPS\Member::loggedIn()->language()->addToStack('days'), 'prune_log_moderator' ) );
|
||||
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$form->saveAsSettings();
|
||||
\IPS\Session::i()->log( 'acplog__statsonlineusers_settings' );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=stats&controller=deviceusage' ), 'saved' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('prunesettings');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('global')->block( 'prunesettings', $form, FALSE );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Member Activity
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 10 Jan 2018
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\admin\stats;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Member Activity
|
||||
*/
|
||||
class _membersactivity extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'membersactivity_manage' );
|
||||
parent::execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Member activity statistics
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
{
|
||||
$count = NULL;
|
||||
$table = NULL;
|
||||
$start = NULL;
|
||||
$end = NULL;
|
||||
|
||||
$defaults = array( 'start' => \IPS\DateTime::create()->setDate( date('Y'), date('m'), 1 ), 'end' => new \IPS\DateTime );
|
||||
|
||||
if( isset( \IPS\Request::i()->postDateStart ) AND isset( \IPS\Request::i()->postDateEnd ) )
|
||||
{
|
||||
$defaults = array( 'start' => \IPS\DateTime::ts( \IPS\Request::i()->postDateStart ), 'end' => \IPS\DateTime::ts( \IPS\Request::i()->postDateEnd ) );
|
||||
}
|
||||
|
||||
$groupOptions = array_combine( array_keys( \IPS\Member\Group::groups( TRUE, FALSE ) ), array_map( function( $_group ) { return (string) $_group; }, \IPS\Member\Group::groups( TRUE, FALSE ) ) );
|
||||
|
||||
if( isset( \IPS\Request::i()->postGroups ) )
|
||||
{
|
||||
$defaultGroups = explode( ',', \IPS\Request::i()->postGroups );
|
||||
}
|
||||
else
|
||||
{
|
||||
$defaultGroups = array_keys( $groupOptions );
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form( 'posts', 'continue' );
|
||||
$form->add( new \IPS\Helpers\Form\DateRange( 'date', $defaults, TRUE ) );
|
||||
$form->add( new \IPS\Helpers\Form\CheckboxSet( 'groups', $defaultGroups, FALSE, array( 'options' => $groupOptions ), NULL, NULL, NULL, 'group_filters' ) );
|
||||
|
||||
if( $values = $form->values() )
|
||||
{
|
||||
/* Determine start and end time */
|
||||
$startTime = $values['date']['start']->getTimestamp();
|
||||
$endTime = $values['date']['end']->getTimestamp();
|
||||
|
||||
$start = $values['date']['start']->html();
|
||||
$end = $values['date']['end']->html();
|
||||
|
||||
$groups = ( count( array_diff( array_keys( $groupOptions ), $values['groups'] ) ) ) ? $values['groups'] : NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Determine start and end time */
|
||||
$startTime = $defaults['start']->getTimestamp();
|
||||
$endTime = $defaults['end']->getTimestamp();
|
||||
|
||||
$start = $defaults['start']->html();
|
||||
$end = $defaults['end']->html();
|
||||
|
||||
$groups = ( count( array_diff( array_keys( $groupOptions ), $defaultGroups ) ) ) ? $defaultGroups : NULL;
|
||||
}
|
||||
|
||||
/* Do we have our date ranges? */
|
||||
if( $start AND $end )
|
||||
{
|
||||
/* Build our where clause */
|
||||
$where = array( array( 'member_last_post BETWEEN ? AND ?', $startTime, $endTime ) );
|
||||
|
||||
if( $groups !== NULL )
|
||||
{
|
||||
$where[] = array( '(' . \IPS\Db::i()->in( 'member_group_id', $groups ) . ' OR ' . \IPS\Db::i()->findInSet( 'mgroup_others', $groups ) . ')' );
|
||||
}
|
||||
|
||||
/* Get the count */
|
||||
$count = \IPS\Db::i()->select( 'COUNT(*)', 'core_members', $where )->first();
|
||||
|
||||
/* And now build the table */
|
||||
$table = new \IPS\Helpers\Table\Db( 'core_members', \IPS\Request::i()->url()->setQueryString( array( 'postDateStart' => $startTime, 'postDateEnd' => $endTime, 'postGroups' => is_array( $groups ) ? implode( ',', $groups ) : NULL ) ), $where );
|
||||
|
||||
$table->include = array( 'name', 'email', 'member_posts', 'member_last_post', 'group_name', 'ip_address' );
|
||||
$table->mainColumn = 'name';
|
||||
$table->langPrefix = 'activity_';
|
||||
$table->rowClasses = array( 'email' => array( 'ipsTable_wrap' ), 'group_name' => array( 'ipsTable_wrap' ) );
|
||||
$table->widths = array( 'group_name' => '25' );
|
||||
|
||||
/* Default sort options */
|
||||
$table->sortBy = $table->sortBy ?: 'member_last_post';
|
||||
$table->sortDirection = $table->sortDirection ?: 'desc';
|
||||
|
||||
/* Custom parsers */
|
||||
$table->parsers = array(
|
||||
'name' => function( $val, $row )
|
||||
{
|
||||
$member = \IPS\Member::constructFromData( $row );
|
||||
return \IPS\Theme::i()->getTemplate( 'global', 'core' )->userPhoto( $member, 'tiny' ) . ' ' . $member->link();
|
||||
},
|
||||
'email' => function( $val, $row )
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate( 'members', 'core', 'admin' )->memberEmailCell( htmlentities( $val, ENT_DISALLOWED, 'UTF-8', FALSE ) );
|
||||
},
|
||||
'member_last_post' => function( $val, $row )
|
||||
{
|
||||
return \IPS\DateTime::ts( $val )->html();
|
||||
},
|
||||
'group_name' => function( $val, $row )
|
||||
{
|
||||
$secondary = \IPS\Member::constructFromData( $row )->groups;
|
||||
|
||||
foreach( $secondary as $k => $v )
|
||||
{
|
||||
if( $v == $row['member_group_id'] or $v == 0 )
|
||||
{
|
||||
unset( $secondary[ $k ] );
|
||||
continue;
|
||||
}
|
||||
|
||||
$secondary[ $k ] = \IPS\Member\Group::load( $v );
|
||||
}
|
||||
|
||||
return \IPS\Theme::i()->getTemplate( 'members', 'core', 'admin' )->groupCell( \IPS\Member\Group::load( $row['member_group_id'] ), $secondary );
|
||||
},
|
||||
'ip_address' => function( $val, $row )
|
||||
{
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'members', 'membertools_ip' ) )
|
||||
{
|
||||
return "<a href='" . \IPS\Http\Url::internal( "app=core&module=members&controller=ip&ip={$val}" ) . "'>{$val}</a>";
|
||||
}
|
||||
return $val;
|
||||
},
|
||||
);
|
||||
|
||||
$table->extraHtml = \IPS\Theme::i()->getTemplate( 'stats' )->tableheader( $start, $end, $count, "member_activity_results" );
|
||||
}
|
||||
|
||||
$formHtml = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'stats' ) ), 'filtersFormTemplate' ) );
|
||||
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'admin_stats.js', 'core' ) );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__core_stats_membersactivity');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'stats' )->memberactivity( $formHtml, $count, $table );
|
||||
}
|
||||
}
|
||||
@@ -52,17 +52,31 @@ class _membervisits extends \IPS\Dispatcher\Controller
|
||||
$defaults = array( 'start' => \IPS\DateTime::ts( \IPS\Request::i()->visitDateStart ), 'end' => \IPS\DateTime::ts( \IPS\Request::i()->visitDateEnd ) );
|
||||
}
|
||||
|
||||
$groupOptions = array_combine( array_keys( \IPS\Member\Group::groups( TRUE, FALSE ) ), array_map( function( $_group ) { return (string) $_group; }, \IPS\Member\Group::groups( TRUE, FALSE ) ) );
|
||||
|
||||
if( isset( \IPS\Request::i()->visitGroups ) )
|
||||
{
|
||||
$defaultGroups = explode( ',', \IPS\Request::i()->visitGroups );
|
||||
}
|
||||
else
|
||||
{
|
||||
$defaultGroups = array_keys( $groupOptions );
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form( 'visits', 'continue' );
|
||||
$form->add( new \IPS\Helpers\Form\DateRange( 'visit_date', $defaults, TRUE ) );
|
||||
$form->add( new \IPS\Helpers\Form\DateRange( 'date', $defaults, TRUE ) );
|
||||
$form->add( new \IPS\Helpers\Form\CheckboxSet( 'groups', $defaultGroups, FALSE, array( 'options' => $groupOptions ), NULL, NULL, NULL, 'group_filters' ) );
|
||||
|
||||
if( $values = $form->values() )
|
||||
{
|
||||
/* Determine start and end time */
|
||||
$startTime = $values['visit_date']['start']->getTimestamp();
|
||||
$endTime = $values['visit_date']['end']->getTimestamp();
|
||||
$startTime = $values['date']['start']->getTimestamp();
|
||||
$endTime = $values['date']['end']->getTimestamp();
|
||||
|
||||
$start = $values['visit_date']['start']->html();
|
||||
$end = $values['visit_date']['end']->html();
|
||||
$start = $values['date']['start']->html();
|
||||
$end = $values['date']['end']->html();
|
||||
|
||||
$groups = ( count( array_diff( array_keys( $groupOptions ), $values['groups'] ) ) ) ? $values['groups'] : NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -72,20 +86,31 @@ class _membervisits extends \IPS\Dispatcher\Controller
|
||||
|
||||
$start = $defaults['start']->html();
|
||||
$end = $defaults['end']->html();
|
||||
|
||||
$groups = ( count( array_diff( array_keys( $groupOptions ), $defaultGroups ) ) ) ? $defaultGroups : NULL;
|
||||
}
|
||||
|
||||
/* Do we have our date ranges? */
|
||||
if( $start AND $end )
|
||||
{
|
||||
/* Build our where clause */
|
||||
$where = array( array( 'last_visit BETWEEN ? AND ?', $startTime, $endTime ) );
|
||||
|
||||
if( $groups !== NULL )
|
||||
{
|
||||
$where[] = array( '(' . \IPS\Db::i()->in( 'member_group_id', $groups ) . ' OR ' . \IPS\Db::i()->findInSet( 'mgroup_others', $groups ) . ')' );
|
||||
}
|
||||
|
||||
/* Get the count */
|
||||
$count = \IPS\Db::i()->select( 'COUNT(*)', 'core_members', array( 'last_visit BETWEEN ? AND ?', $startTime, $endTime ) )->first();
|
||||
$count = \IPS\Db::i()->select( 'COUNT(*)', 'core_members', $where )->first();
|
||||
|
||||
/* And now build the table */
|
||||
$table = new \IPS\Helpers\Table\Db( 'core_members', \IPS\Request::i()->url()->setQueryString( array( 'visitDateStart' => $startTime, 'visitDateEnd' => $endTime ) ), array( array( 'last_visit BETWEEN ? AND ?', $startTime, $endTime ) ) );
|
||||
$table = new \IPS\Helpers\Table\Db( 'core_members', \IPS\Request::i()->url()->setQueryString( array( 'visitDateStart' => $startTime, 'visitDateEnd' => $endTime, 'visitGroups' => is_array( $groups ) ? implode( ',', $groups ) : NULL ) ), $where );
|
||||
|
||||
$table->include = array( 'name', 'last_visit' );
|
||||
$table->include = array( 'name', 'email', 'last_visit', 'group_name', 'ip_address' );
|
||||
$table->mainColumn = 'name';
|
||||
$table->langPrefix = 'visits_';
|
||||
$table->rowClasses = array( 'email' => array( 'ipsTable_wrap' ), 'group_name' => array( 'ipsTable_wrap' ) );
|
||||
|
||||
/* Default sort options */
|
||||
$table->sortBy = $table->sortBy ?: 'last_visit';
|
||||
@@ -98,17 +123,47 @@ class _membervisits extends \IPS\Dispatcher\Controller
|
||||
$member = \IPS\Member::constructFromData( $row );
|
||||
return \IPS\Theme::i()->getTemplate( 'global', 'core' )->userPhoto( $member, 'tiny' ) . ' ' . $member->link();
|
||||
},
|
||||
'email' => function( $val, $row )
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate( 'members', 'core', 'admin' )->memberEmailCell( htmlentities( $val, ENT_DISALLOWED, 'UTF-8', FALSE ) );
|
||||
},
|
||||
'last_visit' => function( $val, $row )
|
||||
{
|
||||
return \IPS\DateTime::ts( $val )->html();
|
||||
},
|
||||
'group_name' => function( $val, $row )
|
||||
{
|
||||
$secondary = \IPS\Member::constructFromData( $row )->groups;
|
||||
|
||||
foreach( $secondary as $k => $v )
|
||||
{
|
||||
if( $v == $row['member_group_id'] or $v == 0 )
|
||||
{
|
||||
unset( $secondary[ $k ] );
|
||||
continue;
|
||||
}
|
||||
|
||||
$secondary[ $k ] = \IPS\Member\Group::load( $v );
|
||||
}
|
||||
|
||||
return \IPS\Theme::i()->getTemplate( 'members', 'core', 'admin' )->groupCell( \IPS\Member\Group::load( $row['member_group_id'] ), $secondary );
|
||||
},
|
||||
'ip_address' => function( $val, $row )
|
||||
{
|
||||
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'members', 'membertools_ip' ) )
|
||||
{
|
||||
return "<a href='" . \IPS\Http\Url::internal( "app=core&module=members&controller=ip&ip={$val}" ) . "'>{$val}</a>";
|
||||
}
|
||||
return $val;
|
||||
},
|
||||
);
|
||||
|
||||
$table->extraHtml = \IPS\Theme::i()->getTemplate( 'stats' )->tableheader( $start, $end, $count );
|
||||
$table->extraHtml = \IPS\Theme::i()->getTemplate( 'stats' )->tableheader( $start, $end, $count, "member_visits_results" );
|
||||
}
|
||||
|
||||
$formHtml = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'stats' ) ), 'visitsFormTemplate' ) );
|
||||
$formHtml = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'stats' ) ), 'filtersFormTemplate' ) );
|
||||
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'admin_stats.js', 'core' ) );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__core_stats_membervisits');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'stats' )->membervisits( $formHtml, $count, $table );
|
||||
}
|
||||
|
||||
@@ -50,11 +50,13 @@ class _errorLogs extends \IPS\Dispatcher\Controller
|
||||
$table->parsers = array(
|
||||
'log_member' => function( $val )
|
||||
{
|
||||
try
|
||||
$member = \IPS\Member::load( $val );
|
||||
|
||||
if( $member->member_id )
|
||||
{
|
||||
return htmlentities( \IPS\Member::load( $val )->name, \IPS\HTMLENTITIES, 'UTF-8', FALSE );
|
||||
return htmlentities( $member->name, ENT_DISALLOWED, 'UTF-8', FALSE );
|
||||
}
|
||||
catch ( \OutOfBoundsException $e )
|
||||
else
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ class _hookedFiles extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
try
|
||||
{
|
||||
return \IPS\Plugin::load($row['plugin'])->name;
|
||||
return htmlspecialchars( \IPS\Plugin::load($row['plugin'])->name, ENT_DISALLOWED, 'UTF-8', FALSE );
|
||||
}
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
|
||||
@@ -109,27 +109,7 @@ class _recovery extends \IPS\Dispatcher\Controller
|
||||
|
||||
return array( 3, \IPS\Member::loggedIn()->language()->addToStack( 'reset_theme_to_default' ), 75 );
|
||||
break;
|
||||
|
||||
case 3: # Login Handlers
|
||||
$handlersDisabled = array();
|
||||
|
||||
/* Disable all login handlers other than Internal */
|
||||
foreach( \IPS\Login::handlers( TRUE ) AS $key => $handler )
|
||||
{
|
||||
if ( $key != 'Internal' )
|
||||
{
|
||||
$handler->_enabled = FALSE;
|
||||
$handler->save();
|
||||
|
||||
$handlersDisabled[] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
$_SESSION['recoveryLogins'] = $handlersDisabled;
|
||||
|
||||
return array( 4, \IPS\Member::loggedIn()->language()->addToStack( 'disabled_login_handlers' ), 100 );
|
||||
break;
|
||||
|
||||
|
||||
case 4: # Done
|
||||
return NULL;
|
||||
break;
|
||||
@@ -165,14 +145,7 @@ class _recovery extends \IPS\Dispatcher\Controller
|
||||
/* Did we reset the theme? */
|
||||
$theme = $_SESSION['recoveryTheme'];
|
||||
|
||||
/* Did we disable any login handlers? */
|
||||
$logins = array();
|
||||
foreach( $_SESSION['recoveryLogins'] AS $handler )
|
||||
{
|
||||
$logins[] = \IPS\Login\LoginAbstract::constructFromData( \IPS\Db::i()->select( '*', 'core_login_handlers', array( "login_key=?", $handler ) )->first() );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'recovery_mode' );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'support' )->recovery( $apps, $plugins, $theme, $logins );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'support' )->recovery( $apps, $plugins, $theme );
|
||||
}
|
||||
}
|
||||
@@ -175,6 +175,9 @@ class _support extends \IPS\Dispatcher\Controller
|
||||
/* Reset theme maps to make sure bad data hasn't been cached by visits mid-setup */
|
||||
foreach( \IPS\Theme::themes() as $id => $set )
|
||||
{
|
||||
/* Invalidate template disk cache */
|
||||
$set->cache_key = md5( microtime() . mt_rand( 0, 1000 ) );
|
||||
|
||||
/* Update mappings */
|
||||
$set->css_map = array();
|
||||
$set->save();
|
||||
@@ -536,9 +539,7 @@ class _support extends \IPS\Dispatcher\Controller
|
||||
'toolbars' => \IPS\Settings::i()->ckeditor_toolbars,
|
||||
);
|
||||
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => '' ), array( 'conf_key=?', 'ckeditor_extraPlugins' ) );
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => '' ), array( 'conf_key=?', 'ckeditor_toolbars' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
\IPS\Settings::i()->changeValues( array( 'ckeditor_extraPlugins' => '', 'ckeditor_toolbars' => '' ) );
|
||||
|
||||
$restoredEditor = TRUE;
|
||||
}
|
||||
@@ -632,9 +633,7 @@ class _support extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$editorConfigutation = \IPS\Data\Store::i()->editorConfiguationToRestore;
|
||||
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => $editorConfigutation['extraPlugins'] ), array( 'conf_key=?', 'ckeditor_extraPlugins' ) );
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => $editorConfigutation['toolbars'] ), array( 'conf_key=?', 'ckeditor_toolbars' ) );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
\IPS\Settings::i()->changeValues( array( 'ckeditor_extraPlugins' => $editorConfigutation['extraPlugins'], 'ckeditor_toolbars' => $editorConfigutation['toolbars'] ) );
|
||||
|
||||
unset( \IPS\Data\Store::i()->editorConfiguationToRestore );
|
||||
}
|
||||
|
||||
@@ -84,7 +84,8 @@ class _systemLogs extends \IPS\Dispatcher\Controller
|
||||
$table->langPrefix = 'log_';
|
||||
$table->include = array( 'time', 'category', 'message' );
|
||||
$table->parsers = array(
|
||||
'message' => function( $val, $row ) {
|
||||
'message' => function( $val, $row )
|
||||
{
|
||||
if ( mb_strlen( $val ) > 100 )
|
||||
{
|
||||
$val = mb_substr( $val, 0, 100 ) . '...';
|
||||
@@ -94,15 +95,17 @@ class _systemLogs extends \IPS\Dispatcher\Controller
|
||||
$val = "{$row['exception_class']} ({$row['exception_code']})\n{$val}";
|
||||
}
|
||||
|
||||
$val = htmlspecialchars( $val, \IPS\HTMLENTITIES, 'UTF-8', FALSE );
|
||||
$val = htmlspecialchars( $val, ENT_DISALLOWED, 'UTF-8', FALSE );
|
||||
|
||||
return $val;
|
||||
},
|
||||
'time' => function( $val ) {
|
||||
'time' => function( $val )
|
||||
{
|
||||
return \IPS\DateTime::ts( $val );
|
||||
},
|
||||
'member_id' => function ( $val ){
|
||||
return \IPS\Member::load( $val )->name;
|
||||
'member_id' => function ( $val )
|
||||
{
|
||||
return htmlspecialchars( \IPS\Member::load( $val )->name, ENT_DISALLOWED, 'UTF-8', FALSE );
|
||||
}
|
||||
);
|
||||
$table->sortBy = $table->sortBy ?: 'time';
|
||||
@@ -234,7 +237,8 @@ class _systemLogs extends \IPS\Dispatcher\Controller
|
||||
$table = new \IPS\Helpers\Table\Custom( $source, \IPS\Http\Url::internal( 'app=core&module=support&controller=systemLogs&do=fileLogs' ) );
|
||||
$table->langPrefix = 'log_';
|
||||
$table->parsers = array(
|
||||
'time' => function( $val ) {
|
||||
'time' => function( $val )
|
||||
{
|
||||
return \IPS\DateTime::ts( $val );
|
||||
}
|
||||
);
|
||||
|
||||
@@ -43,7 +43,7 @@ class _utf8mb4 extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('utf8mb4_converter');
|
||||
|
||||
/* Check it isn't utf8mb4 already */
|
||||
if ( \IPS\Settings::i()->getFromConfGlobal('sql_utf8mb4') )
|
||||
if ( \IPS\Settings::i()->getFromConfGlobal('sql_utf8mb4') === TRUE)
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('global', 'core')->message( 'utf8mb4_converter_finished', 'success' );
|
||||
return;
|
||||
@@ -74,7 +74,7 @@ class _utf8mb4 extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$form = new \IPS\Helpers\Form( 'utf8mb4_converter_intro', 'continue' );
|
||||
$form->hiddenValues['continue'] = 1;
|
||||
$form->addMessage( 'utf8mb4_converter_explain' );
|
||||
$form->addMessage( \IPS\CIC ? 'utf8mb4_converter_cic_explain' : 'utf8mb4_converter_explain' );
|
||||
|
||||
if ( $form->values() )
|
||||
{
|
||||
@@ -233,7 +233,7 @@ class _utf8mb4 extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/* If this is the search index table, initiate rebuild now. */
|
||||
if( $table == 'core_search_index' )
|
||||
if( $table == 'core_search_index' and \IPS\Settings::i()->search_method == 'mysql' )
|
||||
{
|
||||
\IPS\Content\Search\Index::i()->rebuild();
|
||||
}
|
||||
|
||||
@@ -89,6 +89,12 @@ class _ajax extends \IPS\core\modules\front\system\ajax
|
||||
$keywords[ $word['url'] ]['keywords'][] = $word['keyword'];
|
||||
}
|
||||
|
||||
/* Make sure the keywords are unique */
|
||||
foreach( $keywords as $url => $entry )
|
||||
{
|
||||
$keywords[ $url ]['keywords'] = array_unique( $entry['keywords'] );
|
||||
}
|
||||
|
||||
\file_put_contents( \IPS\ROOT_PATH . "/applications/{$qs['app']}/data/acpsearch.json", json_encode( $keywords, version_compare( PHP_VERSION, '5.4.0' ) >= 0 ? JSON_PRETTY_PRINT : 0 ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -28,40 +28,49 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
{
|
||||
{
|
||||
/* Init login class */
|
||||
$url = \IPS\Http\Url::internal( "app=core&module=system&controller=login", 'admin', NULL, array(), \IPS\Settings::i()->logins_over_https );
|
||||
$url = \IPS\Http\Url::internal( "app=core&module=system&controller=login", 'admin' );
|
||||
if ( isset( \IPS\Request::i()->ref ) )
|
||||
{
|
||||
$url = $url->setQueryString( 'ref', \IPS\Request::i()->ref );
|
||||
}
|
||||
$login = new \IPS\Login( $url );
|
||||
$login->flagOptions = FALSE;
|
||||
$login = new \IPS\Login( $url, \IPS\Login::LOGIN_ACP );
|
||||
|
||||
/* Set the default tab */
|
||||
$forms = $login->forms( TRUE, ( \IPS\Request::i()->ref ?: TRUE ) );
|
||||
|
||||
$this->activeTab = \IPS\Request::i()->tab ?: key($forms);
|
||||
|
||||
/* Process */
|
||||
/* Authenticate */
|
||||
$error = NULL;
|
||||
try
|
||||
{
|
||||
/* Authenticate */
|
||||
$member = $login->authenticate();
|
||||
if ( $member !== NULL and $member->member_id )
|
||||
/* If we were successful... */
|
||||
if ( $success = $login->authenticate() )
|
||||
{
|
||||
/* Success */
|
||||
if ( $member->isAdmin() )
|
||||
/* Check we can actually access the ACP */
|
||||
if ( $success->member->isAdmin() )
|
||||
{
|
||||
$this->_doLogin( $member );
|
||||
/* If we need to do two-factor authentication, do that */
|
||||
if ( $success->mfa( 'AuthenticateAdmin' ) )
|
||||
{
|
||||
$_SESSION['processing2FA'] = array( 'memberId' => $success->member->member_id );
|
||||
|
||||
$url = \IPS\Http\Url::internal( 'app=core&module=system&controller=login&do=mfa', 'admin', 'login' );
|
||||
if ( isset( \IPS\Request::i()->ref ) )
|
||||
{
|
||||
$url = $url->setQueryString( 'ref', \IPS\Request::i()->ref );
|
||||
}
|
||||
if ( isset( \IPS\Request::i()->auth ) )
|
||||
{
|
||||
$url = $url->setQueryString( 'auth', \IPS\Request::i()->auth );
|
||||
}
|
||||
\IPS\Output::i()->redirect( $url );
|
||||
}
|
||||
|
||||
/* Otherwise go ahead */
|
||||
$this->_doLogin( $success->member );
|
||||
}
|
||||
/* Error */
|
||||
/* ... otherwise show an error */
|
||||
else
|
||||
{
|
||||
$error = 'no_access_cp';
|
||||
|
||||
/* Log */
|
||||
$this->log( 'fail' );
|
||||
}
|
||||
}
|
||||
@@ -69,11 +78,10 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
catch ( \IPS\Login\Exception $e )
|
||||
{
|
||||
$error = $e->getMessage();
|
||||
|
||||
/* Log */
|
||||
$this->log( 'fail' );
|
||||
}
|
||||
|
||||
/* Have we been sent here because of an IP address mismatch? */
|
||||
if ( is_null( $error ) AND isset( \IPS\Request::i()->error ) )
|
||||
{
|
||||
switch( \IPS\Request::i()->error )
|
||||
@@ -87,16 +95,8 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get icons */
|
||||
$icons = array();
|
||||
$haveStandard = FALSE;
|
||||
foreach ( \IPS\Login::handlers() as $key => $handler )
|
||||
{
|
||||
$icons[ $key ] = $handler::$icon;
|
||||
}
|
||||
|
||||
/* Do we need an error? */
|
||||
/* Do we need to show a message about an unfinished upgrade? */
|
||||
$upgradeError = FALSE;
|
||||
if ( !\IPS\IN_DEV and !isset( \IPS\Request::i()->noWarning ) )
|
||||
{
|
||||
@@ -109,7 +109,7 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
/* Display Login Form */
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'admin_system.js', 'core', 'admin' ) );
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'system/login.css', 'core', 'admin' ) );
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'system' )->login( $forms, $this->activeTab, $error, $icons, $upgradeError ) );
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'system' )->login( $login, $error, $upgradeError ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -203,6 +203,9 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the cookie */
|
||||
\IPS\Request::i()->setCookie( 'acp_login_key', \IPS\Session::i()->cookieKey );
|
||||
|
||||
/* Boink - if we're in recovery mode, go there */
|
||||
if ( \IPS\RECOVERY_MODE === TRUE )
|
||||
{
|
||||
@@ -252,4 +255,5 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
|
||||
\IPS\Db::i()->insert( 'core_admin_login_logs', $save );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,7 +21,12 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
* upgrade
|
||||
*/
|
||||
class _upgrade extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
{
|
||||
/**
|
||||
* @brief IPS clientArea Password
|
||||
*/
|
||||
protected $_clientAreaPassword;
|
||||
|
||||
/**
|
||||
* Manage
|
||||
*
|
||||
@@ -29,10 +34,8 @@ class _upgrade extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function manage()
|
||||
{
|
||||
protected function manage()
|
||||
{
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'upgrade_manage' );
|
||||
\IPS\Dispatcher::i()->checkAcpPermission( 'upgrade_manage', 'core', 'overview' );
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::external( "http://ipbmafia.ru/files/file/1560-ips-community-suite-41-nulled/" ) );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::external( "http://ipbmafia.ru/files/file/2134-invision-community-42-nulled/" ) );
|
||||
}
|
||||
}
|
||||
@@ -60,6 +60,10 @@ class _directory extends \IPS\Dispatcher\Controller
|
||||
protected function manage()
|
||||
{
|
||||
$baseUrl = \IPS\Http\Url::internal( 'app=core&module=clubs&controller=directory', 'front', 'clubs_list' );
|
||||
if ( isset( \IPS\Request::i()->view ) and in_array( \IPS\Request::i()->view, array( 'grid', 'list' ) ) )
|
||||
{
|
||||
$baseUrl = $baseUrl->setQueryString( 'view', \IPS\Request::i()->view );
|
||||
}
|
||||
|
||||
/* All Clubs: Sort */
|
||||
$sortOption = \IPS\Settings::i()->clubs_default_sort;
|
||||
@@ -71,11 +75,25 @@ class _directory extends \IPS\Dispatcher\Controller
|
||||
/* All Clubs: Filters */
|
||||
$filters = array();
|
||||
$mineOnly = FALSE;
|
||||
$extraWhere = NULL;
|
||||
if ( isset( \IPS\Request::i()->filter ) and \IPS\Request::i()->filter === 'mine' )
|
||||
{
|
||||
$mineOnly = TRUE;
|
||||
$baseUrl = $baseUrl->setQueryString( 'filter', 'mine' );
|
||||
}
|
||||
if ( isset( \IPS\Request::i()->type ) and in_array( \IPS\Request::i()->type, array( 'free', 'paid' ) ) )
|
||||
{
|
||||
$baseUrl = $baseUrl->setQueryString( 'type', \IPS\Request::i()->type );
|
||||
|
||||
if ( \IPS\Request::i()->type === 'free' )
|
||||
{
|
||||
$extraWhere[] = array( 'fee IS NULL' );
|
||||
}
|
||||
else
|
||||
{
|
||||
$extraWhere[] = array( 'fee IS NOT NULL' );
|
||||
}
|
||||
}
|
||||
foreach ( \IPS\Member\Club\CustomField::fields() as $field )
|
||||
{
|
||||
$k = "f{$field->id}";
|
||||
@@ -100,7 +118,14 @@ class _directory extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
if ( isset( $options[ $id ] ) )
|
||||
{
|
||||
$filters[ $field->id ][ $id ] = $options[ $id ];
|
||||
if( $field->type == 'CheckboxSet' )
|
||||
{
|
||||
$filters[ $field->id ][ $id ] = $id;
|
||||
}
|
||||
else
|
||||
{
|
||||
$filters[ $field->id ][ $id ] = $options[ $id ];
|
||||
}
|
||||
}
|
||||
}
|
||||
$baseUrl = $baseUrl->setQueryString( 'f' . $field->id, array_keys( $filters[ $field->id ] ) );
|
||||
@@ -116,8 +141,8 @@ class _directory extends \IPS\Dispatcher\Controller
|
||||
/* Get All Clubs */
|
||||
$perPage = 24;
|
||||
$page = isset( \IPS\Request::i()->page ) ? intval( \IPS\Request::i()->page ) : 1;
|
||||
$allClubs = \IPS\Member\Club::clubs( \IPS\Member::loggedIn(), array( ( $page - 1 ) * $perPage, $perPage ), $sortOption, $mineOnly, $filters );
|
||||
$pagination = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $baseUrl, ceil( $allClubs->count( TRUE ) / $perPage ), $page, $perPage );
|
||||
$allClubs = \IPS\Member\Club::clubs( \IPS\Member::loggedIn(), array( ( $page - 1 ) * $perPage, $perPage ), $sortOption, $mineOnly, $filters, $extraWhere );
|
||||
$pagination = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $baseUrl, ceil( ( is_object( $allClubs ) ? $allClubs->count( TRUE ) : 0 ) / $perPage ), $page, $perPage );
|
||||
|
||||
/* Get my clubs */
|
||||
$myClubsActivity = NULL;
|
||||
@@ -128,7 +153,7 @@ class _directory extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Build Map */
|
||||
$mapMarkers = NULL;
|
||||
if ( \IPS\Settings::i()->googlemaps and \IPS\Settings::i()->google_maps_api_key )
|
||||
if ( \IPS\GeoLocation::enabled() )
|
||||
{
|
||||
$mapMarkers = array();
|
||||
|
||||
@@ -139,7 +164,7 @@ class _directory extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
elseif ( !\IPS\Member::loggedIn()->modPermission('can_access_all_clubs') )
|
||||
{
|
||||
$where[] = array( "( type<>? OR status IN('" . \IPS\Member\Club::STATUS_MEMBER . "','" . \IPS\Member\Club::STATUS_MODERATOR . "','" . \IPS\Member\Club::STATUS_LEADER . "') )", \IPS\Member\Club::TYPE_PRIVATE );
|
||||
$where[] = array( "( type<>? OR status IN('" . \IPS\Member\Club::STATUS_MEMBER . "','" . \IPS\Member\Club::STATUS_MODERATOR . "','" . \IPS\Member\Club::STATUS_LEADER . "','" . \IPS\Member\Club::STATUS_EXPIRED . "','" . \IPS\Member\Club::STATUS_EXPIRED_MODERATOR . "') )", \IPS\Member\Club::TYPE_PRIVATE );
|
||||
}
|
||||
|
||||
$select = \IPS\Db::i()->select( array( 'id', 'name', 'location_lat', 'location_long' ), 'core_clubs', $where );
|
||||
@@ -164,8 +189,21 @@ class _directory extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/* Display */
|
||||
$view = \IPS\Settings::i()->clubs_default_view;
|
||||
if ( \IPS\Settings::i()->clubs_allow_view_change )
|
||||
{
|
||||
if ( isset( \IPS\Request::i()->view ) and in_array( \IPS\Request::i()->view, array( 'grid', 'list' ) ) )
|
||||
{
|
||||
\IPS\Request::i()->setCookie( 'clubs_view', \IPS\Request::i()->view, \IPS\DateTime::create()->add( new \DateInterval('P1Y' ) ) );
|
||||
$view = \IPS\Request::i()->view;
|
||||
}
|
||||
elseif ( isset( \IPS\Request::i()->cookie['clubs_view'] ) and in_array( \IPS\Request::i()->cookie['clubs_view'], array( 'grid', 'list' ) ) )
|
||||
{
|
||||
$view = \IPS\Request::i()->cookie['clubs_view'];
|
||||
}
|
||||
}
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('module__core_clubs');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('clubs')->directory( $featuredClubs, $allClubs, $pagination, $baseUrl, $sortOption, $myClubsActivity, $mapMarkers );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('clubs')->directory( $featuredClubs, $allClubs, $pagination, $baseUrl, $sortOption, $myClubsActivity, $mapMarkers, $view );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -187,6 +225,15 @@ class _directory extends \IPS\Dispatcher\Controller
|
||||
) ) ) );
|
||||
}
|
||||
|
||||
if ( \IPS\Application::appIsEnabled( 'nexus' ) and \IPS\Settings::i()->clubs_paid_on )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'club_membership_fee', isset( \IPS\Request::i()->type ) ? \IPS\Request::i()->type : 'all', TRUE, array( 'options' => array(
|
||||
'all' => 'all_clubs',
|
||||
'free' => 'club_membership_free',
|
||||
'paid' => 'club_membership_paid'
|
||||
) ) ) );
|
||||
}
|
||||
|
||||
foreach ( $fields as $field )
|
||||
{
|
||||
if ( $field->filterable )
|
||||
@@ -225,6 +272,11 @@ class _directory extends \IPS\Dispatcher\Controller
|
||||
$url = $url->setQueryString( 'filter', 'mine' );
|
||||
}
|
||||
|
||||
if ( \IPS\Application::appIsEnabled( 'nexus' ) and \IPS\Settings::i()->clubs_paid_on and $values['club_membership_fee'] !== 'all' )
|
||||
{
|
||||
$url = $url->setQueryString( 'type', $values['club_membership_fee'] );
|
||||
}
|
||||
|
||||
foreach ( $fields as $field )
|
||||
{
|
||||
if ( $field->filterable )
|
||||
@@ -273,11 +325,14 @@ class _directory extends \IPS\Dispatcher\Controller
|
||||
protected function create()
|
||||
{
|
||||
$availableTypes = array();
|
||||
foreach ( explode( ',', \IPS\Member::loggedIn()->group['g_create_clubs'] ) as $type )
|
||||
if ( \IPS\Member::loggedIn()->member_id ) // Guests can't create any type of clubs
|
||||
{
|
||||
if ( $type !== '' )
|
||||
foreach ( explode( ',', \IPS\Member::loggedIn()->group['g_create_clubs'] ) as $type )
|
||||
{
|
||||
$availableTypes[ $type ] = 'club_type_' . $type;
|
||||
if ( $type !== '' )
|
||||
{
|
||||
$availableTypes[ $type ] = 'club_type_' . $type;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( !$availableTypes )
|
||||
@@ -285,6 +340,14 @@ class _directory extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->error( \IPS\Member::loggedIn()->member_id ? 'no_module_permission' : 'no_module_permission_guest', '2C349/1', 403, '' );
|
||||
}
|
||||
|
||||
if ( \IPS\Member::loggedIn()->group['g_club_limit'] )
|
||||
{
|
||||
if ( \IPS\Db::i()->select( 'COUNT(*)', 'core_clubs', array( 'owner=?', \IPS\Member::loggedIn()->member_id ) )->first() >= \IPS\Member::loggedIn()->group['g_club_limit'] )
|
||||
{
|
||||
\IPS\Output::i()->error( \IPS\Member::loggedIn()->language()->addToStack( 'too_many_clubs', FALSE, array( 'pluralize' => array( \IPS\Member::loggedIn()->group['g_club_limit'] ) ) ), '2C349/3', 403, '' );
|
||||
}
|
||||
}
|
||||
|
||||
$club = new \IPS\Member\Club;
|
||||
if ( $form = $club->form( FALSE, TRUE, $availableTypes ) )
|
||||
{
|
||||
|
||||
@@ -105,6 +105,12 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
*/
|
||||
protected function manage()
|
||||
{
|
||||
/* Club info in sidebar */
|
||||
if ( \IPS\Settings::i()->clubs_header == 'sidebar' )
|
||||
{
|
||||
\IPS\Output::i()->sidebar['contextual'] = \IPS\Theme::i()->getTemplate( 'clubs', 'core' )->header( $this->club, NULL, 'sidebar' );
|
||||
}
|
||||
|
||||
/* If this is a closed club, and we don't have permission to read it, show the member page instead */
|
||||
if ( $this->club->type == \IPS\Member\Club::TYPE_CLOSED && !$this->club->canRead() )
|
||||
{
|
||||
@@ -113,7 +119,7 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
}
|
||||
|
||||
/* Get the activity stream */
|
||||
$activity = \IPS\Content\Search\Query::init()->filterByClub( $this->club )->setOrder( \IPS\Content\Search\Query::ORDER_NEWEST_UPDATED )->search();
|
||||
$activity = \IPS\Content\Search\Query::init()->filterByClub( $this->club )->setOrder( \IPS\Content\Search\Query::ORDER_NEWEST_CREATED )->search();
|
||||
|
||||
/* Get who joined the club in between those results */
|
||||
if ( $this->club->type != \IPS\Member\Club::TYPE_PUBLIC )
|
||||
@@ -121,7 +127,14 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
$lastTime = NULL;
|
||||
foreach ( $activity as $key => $result )
|
||||
{
|
||||
$lastTime = $result->createdDate->getTimestamp();
|
||||
if ( $result !== NULL )
|
||||
{
|
||||
$lastTime = $result->createdDate->getTimestamp();
|
||||
}
|
||||
else
|
||||
{
|
||||
unset( $activity[ $key ] );
|
||||
}
|
||||
}
|
||||
$joins = array();
|
||||
$joinWhere = array( array( 'club_id=?', $this->club->id ), array( \IPS\Db::i()->in( 'status', array( \IPS\Member\Club::STATUS_MEMBER, \IPS\Member\Club::STATUS_MODERATOR, \IPS\Member\Club::STATUS_LEADER ) ) ) );
|
||||
@@ -132,7 +145,7 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
$select = 'core_clubs_memberships.joined' . ',' . implode( ',', array_map( function( $column ) {
|
||||
return 'core_members.' . $column;
|
||||
}, \IPS\Member::columnsForPhoto() ) );
|
||||
foreach ( \IPS\Db::i()->select( $select, 'core_clubs_memberships', $joinWhere, 'joined DESC', NULL, NULL, NULL, \IPS\Db::SELECT_MULTIDIMENSIONAL_JOINS )->join( 'core_members', 'core_members.member_id=core_clubs_memberships.member_id' ) as $join )
|
||||
foreach ( \IPS\Db::i()->select( $select, 'core_clubs_memberships', $joinWhere, 'joined DESC', array( 0, 50 ), NULL, NULL, \IPS\Db::SELECT_MULTIDIMENSIONAL_JOINS )->join( 'core_members', 'core_members.member_id=core_clubs_memberships.member_id' ) as $join )
|
||||
{
|
||||
$joins[] = new \IPS\Content\Search\Result\Custom(
|
||||
\IPS\DateTime::ts( $join['core_clubs_memberships']['joined'] ),
|
||||
@@ -144,7 +157,7 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
/* Merge them in */
|
||||
if ( !empty( $joins ) )
|
||||
{
|
||||
$activity = array_merge( iterator_to_array( $activity ), $joins );
|
||||
$activity = array_filter( array_merge( iterator_to_array( $activity ), $joins ) );
|
||||
uasort( $activity, function( $a, $b )
|
||||
{
|
||||
if ( $a->createdDate->getTimestamp() == $b->createdDate->getTimestamp() )
|
||||
@@ -163,7 +176,8 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
}
|
||||
}
|
||||
|
||||
/* Display */
|
||||
/* Display */
|
||||
\IPS\Output::i()->linkTags['canonical'] = (string) $this->club->url();
|
||||
\IPS\Output::i()->title = $this->club->name;
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('clubs')->view( $this->club, $activity, $this->club->fieldValues() );
|
||||
}
|
||||
@@ -215,7 +229,7 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
*/
|
||||
protected function editPhoto()
|
||||
{
|
||||
if ( !( $this->club->owner and $this->club->owner == \IPS\Member::loggedIn() ) and !\IPS\Member::loggedIn()->modPermission('can_access_all_clubs') )
|
||||
if ( !$this->club->isLeader() )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C350/R', 403, '' );
|
||||
}
|
||||
@@ -301,7 +315,7 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
$form->add( new \IPS\Helpers\Form\Custom('photo_crop', array( 0, 0, $suggestedWidth, $suggestedHeight ), FALSE, array(
|
||||
'getHtml' => function( $field ) use ( $original )
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate('profile')->photoCrop( $field->name, $field->value, $this->club->url()->setQueryString( 'do', 'cropPhotoGetPhoto' )->csrf() );
|
||||
return \IPS\Theme::i()->getTemplate('members', 'core', 'global')->photoCrop( $field->name, $field->value, $this->club->url()->setQueryString( 'do', 'cropPhotoGetPhoto' )->csrf() );
|
||||
}
|
||||
) ) );
|
||||
|
||||
@@ -323,7 +337,7 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
|
||||
/* Save it */
|
||||
$croppedFilename = mb_substr( $original->originalFilename, 0, mb_strrpos( $original->originalFilename, '.' ) ) . '.cropped' . mb_substr( $original->originalFilename, mb_strrpos( $original->originalFilename, '.' ) );
|
||||
$cropped = \IPS\File::create( 'core_Profile', $original->originalFilename, (string) $image );
|
||||
$cropped = \IPS\File::create( 'core_Clubs', $croppedFilename, (string) $image );
|
||||
$this->club->profile_photo = (string) $cropped;
|
||||
$this->club->save();
|
||||
|
||||
@@ -389,12 +403,21 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
}
|
||||
break;
|
||||
|
||||
case \IPS\Member\Club::STATUS_WAITING_PAYMENT:
|
||||
if ( $this->club->isLeader() )
|
||||
{
|
||||
$filter = \IPS\Member\Club::STATUS_WAITING_PAYMENT;
|
||||
$statuses = array( \IPS\Member\Club::STATUS_WAITING_PAYMENT );
|
||||
$baseUrl = $baseUrl->setQueryString( 'filter', \IPS\Member\Club::STATUS_WAITING_PAYMENT );
|
||||
}
|
||||
break;
|
||||
|
||||
case \IPS\Member\Club::STATUS_BANNED:
|
||||
if ( $this->club->isLeader() )
|
||||
{
|
||||
$filter = \IPS\Member\Club::STATUS_BANNED;
|
||||
$statuses = array( \IPS\Member\Club::STATUS_DECLINED, \IPS\Member\Club::STATUS_BANNED );
|
||||
$baseUrl = $baseUrl->setQueryString( 'filter', \IPS\Member\Club::STATUS_REQUESTED );
|
||||
$baseUrl = $baseUrl->setQueryString( 'filter', \IPS\Member\Club::STATUS_BANNED );
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -402,10 +425,19 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
if ( $this->club->isLeader() )
|
||||
{
|
||||
$filter = \IPS\Member\Club::STATUS_INVITED;
|
||||
$statuses = array( \IPS\Member\Club::STATUS_INVITED );
|
||||
$statuses = array( \IPS\Member\Club::STATUS_INVITED, \IPS\Member\Club::STATUS_INVITED_BYPASSING_PAYMENT );
|
||||
$baseUrl = $baseUrl->setQueryString( 'filter', \IPS\Member\Club::STATUS_INVITED );
|
||||
}
|
||||
break;
|
||||
|
||||
case \IPS\Member\Club::STATUS_EXPIRED:
|
||||
if ( $this->club->isLeader() )
|
||||
{
|
||||
$filter = \IPS\Member\Club::STATUS_EXPIRED;
|
||||
$statuses = array( \IPS\Member\Club::STATUS_EXPIRED, \IPS\Member\Club::STATUS_EXPIRED_MODERATOR );
|
||||
$baseUrl = $baseUrl->setQueryString( 'filter', \IPS\Member\Club::STATUS_EXPIRED );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -420,11 +452,18 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
|
||||
/* Sort out the offset */
|
||||
$perPage = 28;
|
||||
|
||||
$activePage = isset( \IPS\Request::i()->page ) ? intval( \IPS\Request::i()->page ) : 1;
|
||||
|
||||
if( $activePage < 1 )
|
||||
{
|
||||
$activePage = 1;
|
||||
}
|
||||
|
||||
$offset = ( $activePage - 1 ) * $perPage;
|
||||
|
||||
/* Fetch them */
|
||||
$members = $this->club->members( $statuses, array( $offset, $perPage ), $orderByClause, $this->club->isLeader() ? 3 : 1 );
|
||||
$members = $this->club->members( $statuses, array( $offset, $perPage ), $orderByClause, $this->club->isLeader() ? 5 : 1 );
|
||||
$pagination = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $baseUrl, ceil( $members->count(TRUE) / $perPage ), $activePage, $perPage );
|
||||
|
||||
/* Display */
|
||||
@@ -434,9 +473,16 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
}
|
||||
else
|
||||
{
|
||||
$staffStatuses = array( \IPS\Member\Club::STATUS_LEADER, \IPS\Member\Club::STATUS_MODERATOR );
|
||||
if ( $this->club->isLeader( \IPS\Member::loggedIn() ) )
|
||||
{
|
||||
$staffStatuses[] = \IPS\Member\Club::STATUS_EXPIRED_MODERATOR;
|
||||
}
|
||||
$clubStaff = $this->club->members( $staffStatuses, NULL, "IF(core_clubs_memberships.status='leader',0,1), core_clubs_memberships.joined ASC", $this->club->isLeader( \IPS\Member::loggedIn() ) ? 5 : 3 );
|
||||
|
||||
\IPS\Output::i()->title = $this->club->name;
|
||||
\IPS\Output::i()->breadcrumb[] = array( $this->club->url()->setQueryString( 'do', 'members' ), \IPS\Member::loggedIn()->language()->addToStack('club_members') );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'clubs' )->members( $this->club, $members, $pagination, $sortBy, $filter );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'clubs' )->members( $this->club, $members, $pagination, $sortBy, $filter, $clubStaff );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -464,7 +510,12 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
}
|
||||
|
||||
/* Add them */
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_MEMBER, TRUE, \IPS\Member::loggedIn(), NULL, TRUE );
|
||||
$status = \IPS\Member\Club::STATUS_MEMBER;
|
||||
if ( $this->club->isPaid() and !isset( \IPS\Request::i()->waiveFee ) )
|
||||
{
|
||||
$status = \IPS\Member\Club::STATUS_WAITING_PAYMENT;
|
||||
}
|
||||
$this->club->addMember( $member, $status, TRUE, \IPS\Member::loggedIn(), NULL, TRUE );
|
||||
$this->club->recountMembers();
|
||||
|
||||
/* Notify the member */
|
||||
@@ -574,7 +625,7 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
|
||||
/* Get member */
|
||||
$member = \IPS\Member::load( \IPS\Request::i()->member );
|
||||
if ( !in_array( $this->club->memberStatus( $member ), array( \IPS\Member\Club::STATUS_MEMBER, \IPS\Member\Club::STATUS_MODERATOR ) ) )
|
||||
if ( !in_array( $this->club->memberStatus( $member ), array( \IPS\Member\Club::STATUS_MEMBER, \IPS\Member\Club::STATUS_EXPIRED, \IPS\Member\Club::STATUS_MODERATOR, \IPS\Member\Club::STATUS_EXPIRED_MODERATOR ) ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C350/7', 403, '' );
|
||||
}
|
||||
@@ -603,14 +654,27 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
}
|
||||
|
||||
/* Get member */
|
||||
$member = \IPS\Member::load( \IPS\Request::i()->member );
|
||||
$member = ( \IPS\Application::appIsEnabled('nexus') and \IPS\Settings::i()->clubs_paid_on ) ? \IPS\nexus\Customer::load( \IPS\Request::i()->member ) : \IPS\Member::load( \IPS\Request::i()->member );
|
||||
if ( $this->club->memberStatus( $member ) != \IPS\Member\Club::STATUS_LEADER )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C350/9', 403, '' );
|
||||
}
|
||||
|
||||
/* Are they expired? */
|
||||
$status = \IPS\Member\Club::STATUS_MEMBER;
|
||||
if ( \IPS\Application::appIsEnabled('nexus') and \IPS\Settings::i()->clubs_paid_on and $this->club->renewal_price )
|
||||
{
|
||||
foreach ( \IPS\core\extensions\nexus\Item\ClubMembership::getPurchases( $member, $this->club->id ) as $purchase )
|
||||
{
|
||||
if ( $purchase->expire and $purchase->expire->getTimestamp() < time() )
|
||||
{
|
||||
$status = \IPS\Member\Club::STATUS_EXPIRED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Promote */
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_MEMBER, TRUE );
|
||||
$this->club->addMember( $member, $status, TRUE );
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( $this->club->url()->setQueryString( 'do', 'members' ) );
|
||||
@@ -633,14 +697,27 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
}
|
||||
|
||||
/* Get member */
|
||||
$member = \IPS\Member::load( \IPS\Request::i()->member );
|
||||
if ( !in_array( $this->club->memberStatus( $member ), array( \IPS\Member\Club::STATUS_MEMBER, \IPS\Member\Club::STATUS_LEADER ) ) )
|
||||
$member = ( \IPS\Application::appIsEnabled('nexus') and \IPS\Settings::i()->clubs_paid_on ) ? \IPS\nexus\Customer::load( \IPS\Request::i()->member ) : \IPS\Member::load( \IPS\Request::i()->member );
|
||||
if ( !in_array( $this->club->memberStatus( $member ), array( \IPS\Member\Club::STATUS_MEMBER, \IPS\Member\Club::STATUS_EXPIRED, \IPS\Member\Club::STATUS_LEADER ) ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C350/L', 403, '' );
|
||||
}
|
||||
|
||||
/* Are they expired? */
|
||||
$status = \IPS\Member\Club::STATUS_MODERATOR;
|
||||
if ( \IPS\Application::appIsEnabled('nexus') and \IPS\Settings::i()->clubs_paid_on and $this->club->renewal_price )
|
||||
{
|
||||
foreach ( \IPS\core\extensions\nexus\Item\ClubMembership::getPurchases( $member, $this->club->id ) as $purchase )
|
||||
{
|
||||
if ( $purchase->expire and $purchase->expire->getTimestamp() < time() )
|
||||
{
|
||||
$status = \IPS\Member\Club::STATUS_EXPIRED_MODERATOR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Promote */
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_MODERATOR, TRUE );
|
||||
$this->club->addMember( $member, $status, TRUE );
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( $this->club->url()->setQueryString( 'do', 'members' ) );
|
||||
@@ -663,14 +740,27 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
}
|
||||
|
||||
/* Get member */
|
||||
$member = \IPS\Member::load( \IPS\Request::i()->member );
|
||||
if ( $this->club->memberStatus( $member ) != \IPS\Member\Club::STATUS_MODERATOR )
|
||||
$member = ( \IPS\Application::appIsEnabled('nexus') and \IPS\Settings::i()->clubs_paid_on ) ? \IPS\nexus\Customer::load( \IPS\Request::i()->member ) : \IPS\Member::load( \IPS\Request::i()->member );
|
||||
if ( !in_array( $this->club->memberStatus( $member ), array( \IPS\Member\Club::STATUS_MODERATOR, \IPS\Member\Club::STATUS_EXPIRED_MODERATOR ) ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C350/N', 403, '' );
|
||||
}
|
||||
|
||||
/* Are they expired? */
|
||||
$status = \IPS\Member\Club::STATUS_MEMBER;
|
||||
if ( \IPS\Application::appIsEnabled('nexus') and \IPS\Settings::i()->clubs_paid_on and $this->club->renewal_price )
|
||||
{
|
||||
foreach ( \IPS\core\extensions\nexus\Item\ClubMembership::getPurchases( $member, $this->club->id ) as $purchase )
|
||||
{
|
||||
if ( $purchase->expire and $purchase->expire->getTimestamp() < time() )
|
||||
{
|
||||
$status = \IPS\Member\Club::STATUS_EXPIRED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Promote */
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_MEMBER, TRUE );
|
||||
$this->club->addMember( $member, $status, TRUE );
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( $this->club->url()->setQueryString( 'do', 'members' ) );
|
||||
@@ -695,17 +785,218 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
/* Get member */
|
||||
$member = \IPS\Member::load( \IPS\Request::i()->member );
|
||||
$status = $this->club->memberStatus( $member );
|
||||
if ( !in_array( $status, array( \IPS\Member\Club::STATUS_MEMBER, \IPS\Member\Club::STATUS_MODERATOR, \IPS\Member\Club::STATUS_LEADER ) ) )
|
||||
|
||||
/* If this was just an invite, then just remove that */
|
||||
if ( in_array( $status, array( \IPS\Member\Club::STATUS_INVITED, \IPS\Member\Club::STATUS_INVITED_BYPASSING_PAYMENT ) ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C350/9', 403, '' );
|
||||
}
|
||||
if ( $this->club->owner and $this->club->owner->member_id === $member->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'club_cannot_remove_owner', '2C350/E', 403, '' );
|
||||
$this->club->removeMember( $member );
|
||||
\IPS\Db::i()->delete( 'core_notifications', array( 'member=? AND notification_app=? AND notification_key=? and item_id=?', $member->member_id, 'core', 'club_invitation', $this->club->id ) );
|
||||
$member->recountNotifications();
|
||||
}
|
||||
|
||||
/* Remove */
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_BANNED, TRUE, \IPS\Member::loggedIn() );
|
||||
/* If they were previously accepted and waiting for payment, treat it as a decline */
|
||||
elseif ( in_array( $status, array( \IPS\Member\Club::STATUS_WAITING_PAYMENT ) ) )
|
||||
{
|
||||
/* Decline them */
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_DECLINED, TRUE, \IPS\Member::loggedIn() );
|
||||
|
||||
/* Notify the member */
|
||||
$notification = new \IPS\Notification( \IPS\Application::load('core'), 'club_response', $this->club, array( $this->club, FALSE ) );
|
||||
$notification->recipients->attach( $member );
|
||||
$notification->send();
|
||||
}
|
||||
|
||||
/* Otherwise check they are actually a member that can be removed */
|
||||
else
|
||||
{
|
||||
if ( !in_array( $status, array( \IPS\Member\Club::STATUS_MEMBER, \IPS\Member\Club::STATUS_MODERATOR, \IPS\Member\Club::STATUS_LEADER, \IPS\Member\Club::STATUS_EXPIRED, \IPS\Member\Club::STATUS_EXPIRED_MODERATOR ) ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C350/9', 403, '' );
|
||||
}
|
||||
if ( $this->club->owner and $this->club->owner->member_id === $member->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'club_cannot_remove_owner', '2C350/E', 403, '' );
|
||||
}
|
||||
|
||||
/* Cancel purchase */
|
||||
if ( \IPS\Application::appIsEnabled('nexus') and \IPS\Settings::i()->clubs_paid_on )
|
||||
{
|
||||
foreach ( \IPS\core\extensions\nexus\Item\ClubMembership::getPurchases( \IPS\nexus\Customer::load( \IPS\Request::i()->member ), $this->club->id ) as $purchase )
|
||||
{
|
||||
$purchase->cancelled = TRUE;
|
||||
$purchase->member->log( 'purchase', array( 'type' => 'cancel', 'id' => $purchase->id, 'name' => $purchase->name ) );
|
||||
$purchase->can_reactivate = FALSE;
|
||||
$purchase->save();
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove */
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_BANNED, TRUE, \IPS\Member::loggedIn() );
|
||||
}
|
||||
|
||||
/* Recount */
|
||||
$this->club->recountMembers();
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( $this->club->url()->setQueryString( 'do', 'members' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Waive membership fee
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function bypassPayment()
|
||||
{
|
||||
/* CSRF Check */
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
/* Permission check */
|
||||
if ( !$this->club->isLeader() or !\IPS\Application::appIsEnabled('nexus') or !\IPS\Settings::i()->clubs_paid_on )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C350/W', 403, '' );
|
||||
}
|
||||
|
||||
/* Get member */
|
||||
$member = \IPS\nexus\Customer::load( \IPS\Request::i()->member );
|
||||
|
||||
/* Do it */
|
||||
switch ( $this->club->memberStatus( $member ) )
|
||||
{
|
||||
/* If they were waiting for payment, just go ahead and promote them to a member */
|
||||
case \IPS\Member\Club::STATUS_WAITING_PAYMENT:
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_MEMBER, TRUE );
|
||||
break;
|
||||
|
||||
/* If they were already in the club, find their purchase and remove the expiry date */
|
||||
case \IPS\Member\Club::STATUS_MEMBER:
|
||||
case \IPS\Member\Club::STATUS_EXPIRED:
|
||||
case \IPS\Member\Club::STATUS_MODERATOR:
|
||||
case \IPS\Member\Club::STATUS_EXPIRED_MODERATOR:
|
||||
case \IPS\Member\Club::STATUS_LEADER:
|
||||
foreach ( \IPS\core\extensions\nexus\Item\ClubMembership::getPurchases( $member, $this->club->id ) as $purchase )
|
||||
{
|
||||
$extra = $purchase->extra;
|
||||
$extra['originalExpire'] = $purchase->expire ? $purchase->expire->getTimestamp() : NULL;
|
||||
$purchase->extra = $extra;
|
||||
$purchase->expire = NULL;
|
||||
$purchase->save();
|
||||
|
||||
$member->log( 'purchase', array( 'type' => 'info', 'info' => 'never_expire', 'id' => $purchase->id, 'name' => $purchase->name ) );
|
||||
}
|
||||
break;
|
||||
|
||||
/* If they have been invited, just change their status to invited bypassing payment */
|
||||
case \IPS\Member\Club::STATUS_INVITED:
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_INVITED_BYPASSING_PAYMENT, TRUE );
|
||||
break;
|
||||
|
||||
/* For anything else, we can't do this... */
|
||||
default:
|
||||
\IPS\Output::i()->error( 'node_error', '2C350/X', 403, '' );
|
||||
}
|
||||
$this->club->recountMembers();
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( $this->club->url()->setQueryString( 'do', 'members' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore Payment
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function restorePayment()
|
||||
{
|
||||
/* CSRF Check */
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
/* Permission check */
|
||||
if ( !$this->club->isLeader() or !\IPS\Application::appIsEnabled('nexus') or !\IPS\Settings::i()->clubs_paid_on )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C350/W', 403, '' );
|
||||
}
|
||||
|
||||
/* Get member */
|
||||
$member = \IPS\nexus\Customer::load( \IPS\Request::i()->member );
|
||||
|
||||
/* Do it */
|
||||
$status = $this->club->memberStatus( $member );
|
||||
switch ( $status )
|
||||
{
|
||||
/* If they were already in the club, find their purchase and restore the expiry date */
|
||||
case \IPS\Member\Club::STATUS_MEMBER:
|
||||
case \IPS\Member\Club::STATUS_EXPIRED:
|
||||
case \IPS\Member\Club::STATUS_MODERATOR:
|
||||
case \IPS\Member\Club::STATUS_EXPIRED_MODERATOR:
|
||||
case \IPS\Member\Club::STATUS_LEADER:
|
||||
|
||||
$foundPurchase = FALSE;
|
||||
foreach ( \IPS\core\extensions\nexus\Item\ClubMembership::getPurchases( $member, $this->club->id ) as $purchase )
|
||||
{
|
||||
$foundPurchase = TRUE;
|
||||
|
||||
if ( !$purchase->renewals or !$purchase->renewals->cost->amount->isZero() )
|
||||
{
|
||||
$purchase->renewals = $this->club->renewalTerm( $purchase->renewal_currency ?: $member->defaultCurrency() );
|
||||
}
|
||||
if ( isset( $purchase->extra['originalExpire'] ) )
|
||||
{
|
||||
$newExpiry = \IPS\DateTime::ts( $purchase->extra['originalExpire'] );
|
||||
}
|
||||
else
|
||||
{
|
||||
$newExpiry = \IPS\DateTime::create()->add( $purchase->renewals->interval );
|
||||
}
|
||||
$purchase->expire = $newExpiry;
|
||||
$purchase->save();
|
||||
$member->log( 'purchase', array( 'type' => 'info', 'info' => 'restored_expire', 'id' => $purchase->id, 'name' => $purchase->name ) );
|
||||
|
||||
if ( $newExpiry->getTimestamp() < time() )
|
||||
{
|
||||
if ( $status === \IPS\Member\Club::STATUS_MEMBER )
|
||||
{
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_EXPIRED, TRUE );
|
||||
}
|
||||
elseif ( $status === \IPS\Member\Club::STATUS_MODERATOR )
|
||||
{
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_EXPIRED_MODERATOR, TRUE );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( $status === \IPS\Member\Club::STATUS_EXPIRED )
|
||||
{
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_MEMBER, TRUE );
|
||||
}
|
||||
elseif ( $status === \IPS\Member\Club::STATUS_EXPIRED_MODERATOR )
|
||||
{
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_MODERATOR, TRUE );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we couldn't find a purchase, we'll have to remove them and re-invite them */
|
||||
if ( !$foundPurchase )
|
||||
{
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_INVITED, TRUE, NULL, \IPS\Member::loggedIn(), TRUE );
|
||||
|
||||
$notification = new \IPS\Notification( \IPS\Application::load('core'), 'club_invitation', $this->club, array( $this->club, \IPS\Member::loggedIn() ), array( 'invitedBy' => \IPS\Member::loggedIn()->member_id ) );
|
||||
$notification->recipients->attach( $member );
|
||||
$notification->send();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
/* If they have been invited, just change their status to invited NOT bypassing payment */
|
||||
case \IPS\Member\Club::STATUS_INVITED_BYPASSING_PAYMENT:
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_INVITED, TRUE );
|
||||
break;
|
||||
|
||||
/* For anything else, we can't do this... */
|
||||
default:
|
||||
\IPS\Output::i()->error( 'node_error', '2C350/X', 403, '' );
|
||||
}
|
||||
$this->club->recountMembers();
|
||||
|
||||
/* Redirect */
|
||||
@@ -729,11 +1020,55 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
/* If this is an open club, or the member was invited, or they have mod access anyway go ahead and add them */
|
||||
if ( $this->memberStatus === \IPS\Member\Club::STATUS_INVITED or $this->club->type === \IPS\Member\Club::TYPE_OPEN or \IPS\Member::loggedIn()->modPermission('can_access_all_clubs') )
|
||||
if ( in_array( $this->memberStatus, array( \IPS\Member\Club::STATUS_INVITED, \IPS\Member\Club::STATUS_INVITED_BYPASSING_PAYMENT, \IPS\Member\Club::STATUS_WAITING_PAYMENT ) ) or $this->club->type === \IPS\Member\Club::TYPE_OPEN or \IPS\Member::loggedIn()->modPermission('can_access_all_clubs') )
|
||||
{
|
||||
$this->club->addMember( \IPS\Member::loggedIn(), \IPS\Member\Club::STATUS_MEMBER, TRUE, NULL, NULL, TRUE );
|
||||
$this->club->recountMembers();
|
||||
$notificationKey = 'club_join';
|
||||
/* Unless they have to pay */
|
||||
if ( $this->club->isPaid() and $this->memberStatus !== \IPS\Member\Club::STATUS_INVITED_BYPASSING_PAYMENT )
|
||||
{
|
||||
if ( $fee = $this->club->joiningFee() )
|
||||
{
|
||||
/* Create the item */
|
||||
$item = new \IPS\core\extensions\nexus\Item\ClubMembership( $this->club->name, $fee );
|
||||
$item->id = $this->club->id;
|
||||
try
|
||||
{
|
||||
$item->tax = \IPS\Settings::i()->clubs_paid_tax ? \IPS\nexus\Tax::load( \IPS\Settings::i()->clubs_paid_tax ) : NULL;
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
if ( \IPS\Settings::i()->clubs_paid_gateways )
|
||||
{
|
||||
$item->paymentMethodIds = explode( ',', \IPS\Settings::i()->clubs_paid_gateways );
|
||||
}
|
||||
$item->renewalTerm = $this->club->renewalTerm( $fee->currency );
|
||||
$item->payTo = $this->club->owner;
|
||||
$item->commission = \IPS\Settings::i()->clubs_paid_commission;
|
||||
if ( $fees = \IPS\Settings::i()->clubs_paid_transfee and isset( $fees[ $fee->currency ] ) )
|
||||
{
|
||||
$item->fee = new \IPS\nexus\Money( $fees[ $fee->currency ]['amount'], $fee->currency );
|
||||
}
|
||||
|
||||
/* Generate the invoice */
|
||||
$invoice = new \IPS\nexus\Invoice;
|
||||
$invoice->currency = $fee->currency;
|
||||
$invoice->member = \IPS\nexus\Customer::loggedIn();
|
||||
$invoice->addItem( $item );
|
||||
$invoice->return_uri = "app=core&module=clubs&controller=view&id={$this->club->id}";
|
||||
$invoice->save();
|
||||
|
||||
/* Take them to it */
|
||||
\IPS\Output::i()->redirect( $invoice->checkoutUrl() );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->error( 'club_paid_unavailable', '1C350/N', 403, '' );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->club->addMember( \IPS\Member::loggedIn(), \IPS\Member\Club::STATUS_MEMBER, TRUE, NULL, NULL, TRUE );
|
||||
$this->club->recountMembers();
|
||||
$notificationKey = 'club_join';
|
||||
}
|
||||
}
|
||||
/* Otherwise, add the request */
|
||||
else
|
||||
@@ -762,7 +1097,7 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
protected function leave()
|
||||
{
|
||||
/* Can we leave? */
|
||||
if ( !in_array( $this->club->memberStatus( \IPS\Member::loggedIn() ), array( \IPS\Member\Club::STATUS_MEMBER, \IPS\Member\Club::STATUS_MODERATOR, \IPS\Member\Club::STATUS_LEADER ) ) or ( $this->club->owner and $this->club->owner->member_id == \IPS\Member::loggedIn()->member_id ) )
|
||||
if ( !in_array( $this->club->memberStatus( \IPS\Member::loggedIn() ), array( \IPS\Member\Club::STATUS_MEMBER, \IPS\Member\Club::STATUS_MODERATOR, \IPS\Member\Club::STATUS_LEADER, \IPS\Member\Club::STATUS_EXPIRED, \IPS\Member\Club::STATUS_EXPIRED_MODERATOR, \IPS\Member\Club::STATUS_WAITING_PAYMENT, \IPS\Member\Club::STATUS_INVITED ) ) or ( $this->club->owner and $this->club->owner->member_id == \IPS\Member::loggedIn()->member_id ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C350/S', 403, '' );
|
||||
}
|
||||
@@ -770,15 +1105,57 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
/* CSRF Check */
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
/* Cancel purchase */
|
||||
if ( \IPS\Application::appIsEnabled('nexus') and \IPS\Settings::i()->clubs_paid_on )
|
||||
{
|
||||
foreach ( \IPS\core\extensions\nexus\Item\ClubMembership::getPurchases( \IPS\nexus\Customer::loggedIn(), $this->club->id ) as $purchase )
|
||||
{
|
||||
$purchase->cancelled = TRUE;
|
||||
$purchase->member->log( 'purchase', array( 'type' => 'cancel', 'id' => $purchase->id, 'name' => $purchase->name ) );
|
||||
$purchase->can_reactivate = FALSE;
|
||||
$purchase->save();
|
||||
}
|
||||
}
|
||||
|
||||
/* Leave */
|
||||
$this->club->removeMember( \IPS\Member::loggedIn() );
|
||||
$this->club->recountMembers();
|
||||
$this->club->save();
|
||||
|
||||
/* Delete the invitation */
|
||||
\IPS\Db::i()->delete( 'core_notifications', array( 'member=? AND notification_app=? AND notification_key=? and item_id=?', \IPS\Member::loggedIn()->member_id, 'core', 'club_invitation', $this->club->id ) );
|
||||
\IPS\Member::loggedIn()->recountNotifications();
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=clubs&controller=directory', 'front', 'clubs_list' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Renew
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function renew()
|
||||
{
|
||||
/* Can we renew? */
|
||||
if ( !in_array( $this->club->memberStatus( \IPS\Member::loggedIn() ), array( \IPS\Member\Club::STATUS_EXPIRED, \IPS\Member\Club::STATUS_EXPIRED_MODERATOR ) ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C350/Y', 403, '' );
|
||||
}
|
||||
|
||||
/* CSRF Check */
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
/* Find the purchase */
|
||||
foreach ( \IPS\core\extensions\nexus\Item\ClubMembership::getPurchases( \IPS\nexus\Customer::loggedIn(), $this->club->id ) as $purchase )
|
||||
{
|
||||
\IPS\Output::i()->redirect( $purchase->url()->setQueryString( array( 'do' => 'renew', 'cycles' => 1 ) )->csrf() );
|
||||
}
|
||||
|
||||
/* Couldn't find it? */
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C350/Z', 500, '' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Invite Members
|
||||
*
|
||||
@@ -794,9 +1171,23 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
$form = new \IPS\Helpers\Form( 'form', 'club_send_invitations' );
|
||||
$form->class = 'ipsForm_vertical';
|
||||
$form->add( new \IPS\Helpers\Form\Member( 'members', NULL, TRUE, array( 'multiple' => NULL ) ) );
|
||||
if ( $this->club->isPaid() and $this->club->isLeader() )
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'club_invite_waive_fee', FALSE ) );
|
||||
if ( $this->club->renewal_price )
|
||||
{
|
||||
\IPS\Member::loggedIn()->language()->words['club_invite_waive_fee_desc'] = \IPS\Member::loggedIn()->language()->addToStack('club_invite_waive_fee_renewal');
|
||||
}
|
||||
}
|
||||
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$status = \IPS\Member\Club::STATUS_INVITED;
|
||||
if ( $this->club->isPaid() and $this->club->isLeader() and $values['club_invite_waive_fee'] )
|
||||
{
|
||||
$status = \IPS\Member\Club::STATUS_INVITED_BYPASSING_PAYMENT;
|
||||
}
|
||||
|
||||
$notification = new \IPS\Notification( \IPS\Application::load('core'), 'club_invitation', $this->club, array( $this->club, \IPS\Member::loggedIn() ), array( 'invitedBy' => \IPS\Member::loggedIn()->member_id ) );
|
||||
foreach ( $values['members'] as $member )
|
||||
{
|
||||
@@ -805,7 +1196,7 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
$memberStatus = $this->club->memberStatus( $member );
|
||||
if ( !$memberStatus or in_array( $memberStatus, array( \IPS\Member\Club::STATUS_INVITED, \IPS\Member\Club::STATUS_REQUESTED, \IPS\Member\Club::STATUS_DECLINED, \IPS\Member\Club::STATUS_BANNED ) ) )
|
||||
{
|
||||
$this->club->addMember( $member, \IPS\Member\Club::STATUS_INVITED, TRUE, NULL, \IPS\Member::loggedIn(), TRUE );
|
||||
$this->club->addMember( $member, $status, TRUE, NULL, \IPS\Member::loggedIn(), TRUE );
|
||||
$notification->recipients->attach( $member );
|
||||
}
|
||||
}
|
||||
@@ -999,6 +1390,52 @@ class _view extends \IPS\Helpers\CoverPhoto\Controller
|
||||
\IPS\Output::i()->output = \IPS\Request::i()->isAjax() ? $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupTemplate' ) ) : $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a node
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function nodeDelete()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
/* Permission check */
|
||||
if ( !$this->club->isLeader() )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C350/AA', 403, '' );
|
||||
}
|
||||
|
||||
/* Load */
|
||||
$class = \IPS\Request::i()->type;
|
||||
try
|
||||
{
|
||||
$node = $class::load( \IPS\Request::i()->node );
|
||||
$club = $node->club();
|
||||
if ( !$club or $club->id !== $this->club->id )
|
||||
{
|
||||
throw new \Exception;
|
||||
}
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C350/AB', 404, '' );
|
||||
}
|
||||
|
||||
/* Permission check */
|
||||
$itemClass = $node::$contentItemClass;
|
||||
if ( !$node->modPermission( 'delete', \IPS\Member::loggedIn() ) and $itemClass::contentCount( $node, TRUE, TRUE, TRUE, 1 ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C350/AC', 403, '' );
|
||||
}
|
||||
|
||||
/* Delete */
|
||||
\IPS\Db::i()->delete( 'core_clubs_node_map', array( 'club_id=? AND node_class=? AND node_id=?', $club->id, $class, $node->_id ) );
|
||||
$node->deleteOrMoveFormSubmit( array() );
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( $club->url() );
|
||||
}
|
||||
|
||||
/* !Cover Photo */
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,7 +31,7 @@ class _contact extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
if ( !\IPS\Member::loggedIn()->canUseContactUs() )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_permission', '2S333/1', 403, '' );
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2S333/1', 403, '' );
|
||||
}
|
||||
|
||||
/* Execute */
|
||||
@@ -100,15 +100,4 @@ class _contact extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Can Use Contact Us
|
||||
*
|
||||
* @return bool
|
||||
* @deprecated 4.3
|
||||
*/
|
||||
public static function canUseContactUs()
|
||||
{
|
||||
return \IPS\Member::loggedIn()->canUseContactUs();
|
||||
}
|
||||
}
|
||||
@@ -145,7 +145,7 @@ class _popular extends \IPS\Dispatcher\Controller
|
||||
$table->sortDirection = $table->sortDirection ?: 'DESC';
|
||||
|
||||
/* Like or what? */
|
||||
if ( \IPS\Settings::i()->reputation_point_types == 'like' )
|
||||
if ( \IPS\Content\Reaction::isLikeMode() )
|
||||
{
|
||||
\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') ) ) );
|
||||
@@ -202,7 +202,7 @@ class _popular extends \IPS\Dispatcher\Controller
|
||||
$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();
|
||||
$firstIndexDate = \IPS\Content\Search\Index::i()->firstIndexDate();
|
||||
$appWhere = null;
|
||||
$descApp = \IPS\Member::loggedIn()->language()->addToStack( 'leaderboard_in_all_apps' );
|
||||
|
||||
@@ -320,13 +320,14 @@ class _popular extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
/* Got an app? */
|
||||
$appWhere = '';
|
||||
/* Do we want results for a specific app */
|
||||
$customApp = FALSE;
|
||||
|
||||
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 ] ) ) );
|
||||
$customApp = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -341,7 +342,7 @@ class _popular extends \IPS\Dispatcher\Controller
|
||||
|
||||
$storeKey = NULL;
|
||||
$hashes = NULL;
|
||||
if ( ! $customStart and ! $customEnd AND ! $appWhere )
|
||||
if ( ! $customStart and ! $customEnd AND ! $customApp )
|
||||
{
|
||||
$storeKey = 'leaderHashes_' . \IPS\Request::i()->time . '-' . md5( implode( ',', \IPS\Member::loggedIn()->groups ) );
|
||||
|
||||
@@ -368,9 +369,9 @@ class _popular extends \IPS\Dispatcher\Controller
|
||||
/* Get rep hashes */
|
||||
$inner = \IPS\Db::i()->select( 'class_type_id_hash, SUM(rep_rating) as total_rep', array( 'core_reputation_index', 'x' ), array( 'rep_date BETWEEN ' . $date->getTimeStamp() . ' AND ' . $endDate->getTimeStamp() . $appWhere ), NULL, NULL, 'class_type_id_hash' );
|
||||
$repHashes = iterator_to_array( \IPS\Db::i()->select( 'class_type_id_hash, total_rep', $inner, NULL, 'x.total_rep desc', array( 0, 500 ) )->setKeyField('class_type_id_hash') );
|
||||
|
||||
|
||||
/* Now filter through permissions */
|
||||
$searchHashes = iterator_to_array( \IPS\Db::i()->select( 'index_class_type_id_hash', array( 'core_search_index', 'si' ), array( array( "( si.index_permissions = '*' OR " . \IPS\Db::i()->findInSet( 'si.index_permissions', \IPS\Member::loggedIn()->groups ) . ' AND si.index_hidden=0 )' ), array( \IPS\Db::i()->in( 'si.index_class_type_id_hash', array_keys( $repHashes ) ) ) ) )->setKeyField('index_class_type_id_hash') );
|
||||
$searchHashes = \IPS\Content\Search\Index::i()->hashesWithPermission( array_keys( $repHashes ), \IPS\Member::loggedIn() );
|
||||
|
||||
/* Filter out rep hashes not in search results */
|
||||
$hashes = array_slice( array_intersect_key( $repHashes, $searchHashes ), 0, 50 );
|
||||
@@ -386,7 +387,7 @@ class _popular extends \IPS\Dispatcher\Controller
|
||||
$or = array();
|
||||
$results = array();
|
||||
$preLoadMembers = array();
|
||||
|
||||
|
||||
if ( count( $hashes ) )
|
||||
{
|
||||
/* Now get the reputation data */
|
||||
@@ -395,25 +396,15 @@ class _popular extends \IPS\Dispatcher\Controller
|
||||
$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 ) . ')';
|
||||
$or[] = \IPS\Content\Search\ContentFilter::init( $class )->onlyInIds( $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 */
|
||||
/* Query and manually sort */
|
||||
$array = \IPS\Content\Search\Query::init()->filterByContent( $or )->search()->getArrayCopy();
|
||||
foreach( $array as $index => $data )
|
||||
{
|
||||
if ( isset( $repData[ $data['index_class'] . '-' . $data['index_object_id'] ] ) )
|
||||
@@ -433,8 +424,13 @@ class _popular extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* 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' );
|
||||
|
||||
$innerQueryWhere = array();
|
||||
$innerQueryWhere[] = array( 'member_received>0 ' . $appWhere . ' and rep_date BETWEEN ' . intval( $date->getTimeStamp() ) . ' AND ' . intval( $endDate->getTimeStamp() ) );
|
||||
$innerQueryWhere[] = \IPS\Db::i()->in( 'member_group_id', \IPS\Settings::i()->leaderboard_excluded_groups, TRUE );
|
||||
|
||||
$innerQuery = \IPS\Db::i()->select( 'core_reputation_index.member_received as member, SUM(rep_rating) as rep', 'core_reputation_index', $innerQueryWhere, NULL, NULL, 'member' )->join( 'core_members', array( 'core_reputation_index.member_received = core_members.member_id' ) );
|
||||
|
||||
foreach( \IPS\Db::i()->select( 'member, rep', array( $innerQuery, 'in' ), NULL, 'rep DESC', 4 )->setKeyField('member')->setValueField('rep') as $member => $rep )
|
||||
{
|
||||
$topContributors[ $member ] = $rep;
|
||||
@@ -455,7 +451,7 @@ class _popular extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/* Work out the description for popular content */
|
||||
if ( \IPS\Settings::i()->reputation_point_types == 'like' )
|
||||
if ( \IPS\Content\Reaction::isLikeMode() )
|
||||
{
|
||||
$popularResultsSingle = 'popular_results_single_desc';
|
||||
$popularResultsMany = 'popular_results_desc';
|
||||
@@ -481,6 +477,12 @@ class _popular extends \IPS\Dispatcher\Controller
|
||||
|
||||
\IPS\Output::i()->linkTags['canonical'] = (string) \IPS\Http\Url::internal( "app=core&module=discover&controller=popular&tab=leaderboard", 'front', 'leaderboard_leaderboard' );
|
||||
|
||||
/* If there are no results tell search engines not to index the page */
|
||||
if( !count( $results ) )
|
||||
{
|
||||
\IPS\Output::i()->metaTags['robots'] = 'noindex';
|
||||
}
|
||||
|
||||
/* 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 );
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
|
||||
* @since 13 Oct 2016
|
||||
*/
|
||||
|
||||
|
||||
@@ -39,7 +39,8 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* 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' ) );
|
||||
\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/streams.css' ) );
|
||||
|
||||
if ( \IPS\Theme::i()->settings['responsive'] )
|
||||
{
|
||||
@@ -121,7 +122,7 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
\IPS\Output::i()->json( array(
|
||||
'url' => $defaultStream->url(),
|
||||
'title' => htmlspecialchars( $defaultStream->_title, ENT_QUOTES | \IPS\HTMLENTITIES, 'UTF-8', FALSE ),
|
||||
'title' => htmlspecialchars( $defaultStream->_title, ENT_QUOTES | ENT_DISALLOWED, '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
|
||||
) );
|
||||
@@ -166,7 +167,7 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
\IPS\Output::i()->json( array(
|
||||
'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 ),
|
||||
'title' => htmlspecialchars( $defaultStream->_title, ENT_QUOTES | ENT_DISALLOWED, 'UTF-8', FALSE ),
|
||||
'id' => $defaultStream->_id
|
||||
) );
|
||||
}
|
||||
@@ -187,7 +188,13 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
/* but only if we haven't submitted the form on this request */
|
||||
if( !\IPS\Request::i()->stream_submitted )
|
||||
{
|
||||
$streamFields = array( 'include_comments', 'classes', 'clubs', 'ownership', 'custom_members', 'read', 'follow', 'followed_types', 'date_type', 'date_start', 'date_end', 'date_relative_days', 'sort', 'tags', 'unread_links' );
|
||||
$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' );
|
||||
|
||||
/* Clubs enabled? */
|
||||
if( \IPS\Settings::i()->clubs )
|
||||
{
|
||||
$streamFields[] = 'clubs';
|
||||
}
|
||||
|
||||
/* Build and format field values */
|
||||
$_values = array();
|
||||
@@ -379,7 +386,7 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
$output = \IPS\Theme::i()->getTemplate('streams')->streamItems( $results, TRUE, ( $stream->id and !$stream->include_comments ) ? 'last_comment' : 'date', $view );
|
||||
|
||||
$return = array(
|
||||
'title' => htmlspecialchars( $stream->_title, \IPS\HTMLENTITIES | ENT_QUOTES, 'UTF-8', FALSE ),
|
||||
'title' => htmlspecialchars( $stream->_title, ENT_DISALLOWED | ENT_QUOTES, 'UTF-8', FALSE ),
|
||||
'blurb' => $stream->blurb(),
|
||||
'config' => json_encode( $stream->config() ),
|
||||
'count' => count( $results ),
|
||||
@@ -484,7 +491,7 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
|
||||
if ( $stream->member != \IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_permission', '2C280/8', 403, '' );
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C280/8', 403, '' );
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form;
|
||||
@@ -599,7 +606,7 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$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(), 'clubs' => \IPS\IPS::classUsesTrait( $containerClass, 'IPS\Content\ClubContainer' ) ), NULL, NULL, NULL, 'stream_containers_' . $class::$title );
|
||||
$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(), 'clubs' => ( \IPS\Settings::i()->clubs AND \IPS\IPS::classUsesTrait( $containerClass, 'IPS\Content\ClubContainer' ) ) ), 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 ) ) );
|
||||
@@ -616,6 +623,11 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function getClubElement()
|
||||
{
|
||||
if( !\IPS\Settings::i()->clubs )
|
||||
{
|
||||
return \IPS\Output::i()->json( array( 'field' => '' ) );
|
||||
}
|
||||
|
||||
$clubOptions = array();
|
||||
foreach ( \IPS\Member\Club::clubs( \IPS\Member::loggedIn(), NULL, 'name', TRUE ) as $club )
|
||||
{
|
||||
@@ -681,25 +693,48 @@ class _streams extends \IPS\Dispatcher\Controller
|
||||
/* Handle submissions */
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
/* 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 )
|
||||
/* 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. First, if we are editing a stream, we need to get our existing stream filters
|
||||
and put these into an array. Then we loop over the input and overwrite the existing filters with what was submitted. If the user
|
||||
never loaded the container filters we'll retain what we had (expected) but if they did and adjusted or removed container filters
|
||||
then we'll update with what they submitted (expected).
|
||||
*/
|
||||
if( $stream->id )
|
||||
{
|
||||
if ( mb_substr( $k, 0, 18 ) == 'stream_containers_' and $v )
|
||||
$currentContainers = $stream->containers ? json_decode( $stream->containers, TRUE ) : array();
|
||||
|
||||
foreach( $currentContainers as $class => $containers )
|
||||
{
|
||||
$vals = explode( ',', $v );
|
||||
$values[ $k ] = array_combine( $vals, $vals );
|
||||
$values['stream_containers_' . $class::$title ] = array_combine( $containers, $containers );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach ( \IPS\Request::i() as $k => $v )
|
||||
{
|
||||
if ( mb_substr( $k, 0, 18 ) == 'stream_containers_' )
|
||||
{
|
||||
if( $v )
|
||||
{
|
||||
$vals = explode( ',', $v );
|
||||
$values[ $k ] = array_combine( $vals, $vals );
|
||||
}
|
||||
elseif( isset( $values[ $k ] ) )
|
||||
{
|
||||
$values[ $k ] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Update only */
|
||||
if ( isset( \IPS\Request::i()->updateOnly ) )
|
||||
{
|
||||
$formattedValues = $stream->formatFormValues( $values );
|
||||
|
||||
|
||||
foreach ( array( 'include_comments', 'classes', 'containers', 'clubs', '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 ] )
|
||||
|
||||
if ( array_key_exists( $k, $formattedValues ) AND $stream->$k != $formattedValues[ $k ] )
|
||||
{
|
||||
$stream->$k = $formattedValues[ $k ];
|
||||
$stream->baseUrl = $stream->baseUrl->setQueryString( 'stream_' . $k, \IPS\Request::i()->$requestKey );
|
||||
|
||||
@@ -50,6 +50,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
{
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_profile.js', 'core' ) );
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_statuses.js', 'core' ) );
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'global_core.js', 'core', 'global' ) );
|
||||
\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' ) );
|
||||
@@ -57,7 +58,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
if ( \IPS\Theme::i()->settings['responsive'] )
|
||||
{
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/profiles_responsive.css' ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Go */
|
||||
@@ -103,9 +104,17 @@ 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()->page && $canAccessStatuses )
|
||||
if ( \IPS\Request::i()->status && \IPS\Request::i()->isAjax() && \IPS\Request::i()->page && $canAccessStatuses && !isset( \IPS\Request::i()->getUploader ) )
|
||||
{
|
||||
$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/M', 404, '' );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'statuses' )->statusReplies( $status );
|
||||
return;
|
||||
}
|
||||
@@ -167,11 +176,10 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* What tabs are available? */
|
||||
$tabs = array( 'activity' => 'users_activity_feed' );
|
||||
|
||||
if ( \IPS\Settings::i()->clubs )
|
||||
if ( \IPS\Settings::i()->clubs and count( \IPS\Member\Club::clubs( \IPS\Member::loggedIn(), NULL, 'created', $this->member ) ) )
|
||||
{
|
||||
$tabs['clubs'] = 'users_clubs';
|
||||
}
|
||||
@@ -279,7 +287,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
$perPage = 24;
|
||||
$page = isset( \IPS\Request::i()->page ) ? intval( \IPS\Request::i()->page ) : 1;
|
||||
$allClubs = \IPS\Member\Club::clubs( \IPS\Member::loggedIn(), array( ( $page - 1 ) * $perPage, $perPage ), 'last_activity', $this->member );
|
||||
$pagination = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $baseUrl, ceil( $allClubs->count( TRUE ) / $perPage ), $page, $perPage );
|
||||
$pagination = \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $baseUrl, ( ceil( is_object( $allClubs ) ? $allClubs->count( TRUE ) : 0 ) / $perPage ), $page, $perPage );
|
||||
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/clubs.css', 'core', 'front' ) );
|
||||
if ( \IPS\Theme::i()->settings['responsive'] )
|
||||
@@ -376,7 +384,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
'@context' => "http://schema.org",
|
||||
'@type' => "ProfilePage",
|
||||
'url' => (string) $this->member->url(),
|
||||
'name' => htmlspecialchars( $this->member->name, ENT_QUOTES | \IPS\HTMLENTITIES, 'UTF-8', FALSE ),
|
||||
'name' => $this->member->name,
|
||||
'primaryImageOfPage' => array(
|
||||
'@type' => "ImageObject",
|
||||
'contentUrl' => (string) $this->member->get_photo(),
|
||||
@@ -403,7 +411,9 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
\IPS\Output::i()->linkTags['canonical'] = (string) $this->member->url();
|
||||
|
||||
/* Output */
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_profile.js', 'core' ) );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'profile' )->profile( $this->member, $mainContent, $visitors, $sidebarFields, $followers, $addWarningUrl );
|
||||
@@ -439,15 +449,13 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
{
|
||||
foreach( $router->classes as $class )
|
||||
{
|
||||
if( !isset( $class::$includeInUserProfiles ) OR !$class::$includeInUserProfiles )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Add CSS for this app */
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'profile.css', $class::$application ) );
|
||||
|
||||
$types[ $class::$application . '_' . $class::$module ][ mb_strtolower( str_replace( '\\', '_', mb_substr( $class, 4 ) ) ) ] = $class;
|
||||
|
||||
if ( isset( $class::$databaseColumnMap['author'] ) )
|
||||
{
|
||||
$types[ $class::$application . '_' . $class::$module ][ mb_strtolower( str_replace( '\\', '_', mb_substr( $class, 4 ) ) ) ] = $class;
|
||||
}
|
||||
|
||||
$supportsComments = ( in_array( 'IPS\Content\Item', class_parents( $class ) ) and $class::supportsComments( \IPS\Member::loggedIn() ) );
|
||||
if ( $supportsComments )
|
||||
@@ -516,8 +524,16 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
\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 );
|
||||
$pagination = trim( \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $this->member->url()->setQueryString( array( 'do' => 'content', 'all_activity' => 1 ) ), ceil( $results->count( TRUE ) / $query->resultsToGet ), $page, $query->resultsToGet ) );
|
||||
if ( \IPS\Request::i()->isAjax() AND \IPS\Request::i()->all_activity )
|
||||
{
|
||||
\IPS\Output::i()->json( array( 'rows' => \IPS\Theme::i()->getTemplate('profile')->userContentStream( $this->member, $results, $pagination ) ) );
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
$output = \IPS\Theme::i()->getTemplate('profile')->userContentStream( $this->member, $results, $pagination );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -667,9 +683,35 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get the reputation summary */
|
||||
$reactions = array( 'given' => array(), 'received' => array() );
|
||||
|
||||
foreach( \IPS\Db::i()->select( 'reaction, COUNT(*) as count', 'core_reputation_index', array( 'member_id=?', $this->member->member_id ), NULL, NULL, 'reaction' ) as $reaction )
|
||||
{
|
||||
try
|
||||
{
|
||||
$object = \IPS\Content\Reaction::load( $reaction['reaction'] );
|
||||
|
||||
$reactions['given'][] = array( 'count' => $reaction['count'], 'reaction' => $object );
|
||||
}
|
||||
catch( \UnderflowException $e ){}
|
||||
}
|
||||
|
||||
foreach( \IPS\Db::i()->select( 'reaction, COUNT(*) as count', 'core_reputation_index', array( 'member_received=?', $this->member->member_id ), NULL, NULL, 'reaction' ) as $reaction )
|
||||
{
|
||||
try
|
||||
{
|
||||
$object = \IPS\Content\Reaction::load( $reaction['reaction'] );
|
||||
|
||||
$reactions['received'][] = array( 'count' => $reaction['count'], 'reaction' => $object );
|
||||
}
|
||||
catch( \UnderflowException $e ){}
|
||||
}
|
||||
|
||||
|
||||
\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 );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'profile' )->userReputation( $this->member, $types, $currentAppModule, $currentType, (string) $table, $reactions );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -741,7 +783,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form( 'form', 'status_save' );
|
||||
$form->class = 'ipsForm_vertical';
|
||||
$form->class = 'ipsForm_vertical ipsForm_noLabels';
|
||||
|
||||
$formElements = \IPS\core\Statuses\Status::formElements( $status );
|
||||
$form->add( $formElements['status_content'] );
|
||||
@@ -755,7 +797,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
\IPS\Output::i()->redirect( $status->url() );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->output = $form;
|
||||
\IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupTemplate' ) );
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
@@ -763,6 +805,54 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit Status Reply
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function editStatusReply()
|
||||
{
|
||||
try
|
||||
{
|
||||
$reply = \IPS\core\Statuses\Reply::loadAndCheckPerms( \IPS\Request::i()->reply );
|
||||
if ( !$reply->canEdit() )
|
||||
{
|
||||
throw new \DomainException;
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form->class = 'ipsForm_vertical';
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Editor( 'comment_value', $reply->content, TRUE, array(
|
||||
'app' => 'core',
|
||||
'key' => 'Members',
|
||||
'autoSaveKey' => 'editComment-core/members-' . $reply->id,
|
||||
'attachIds' => $reply->attachmentIds()
|
||||
) ) );
|
||||
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
$reply->editContents( $values['comment_value'] );
|
||||
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->output = $reply->html();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->redirect( $reply->url() );
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupTemplate' ) );
|
||||
}
|
||||
catch( \Exception $e )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C138/K', 404, '' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit Profile
|
||||
*
|
||||
@@ -931,24 +1021,27 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
$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'] ) ) )
|
||||
if( isset( $values['bday'] ) )
|
||||
{
|
||||
$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'] ) 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 ( $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'] ) )
|
||||
@@ -980,14 +1073,21 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
{
|
||||
$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\Upload )
|
||||
{
|
||||
$profileFields[ "field_{$id}" ] = (string) $values[ $field->name ];
|
||||
}
|
||||
else
|
||||
{
|
||||
$profileFields[ "field_{$id}" ] = $field::stringValue( $values[ $field->name ] );
|
||||
}
|
||||
|
||||
if ( $field instanceof \IPS\Helpers\Form\Editor )
|
||||
{
|
||||
@@ -1076,17 +1176,6 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
}
|
||||
}
|
||||
|
||||
/* ProfileSync (Facebook, etc.) */
|
||||
foreach ( \IPS\core\ProfileSync\ProfileSyncAbstract::services() as $key => $class )
|
||||
{
|
||||
$obj = new $class( $this->member );
|
||||
if ( $obj->connected() )
|
||||
{
|
||||
$langKey = 'profilesync__' . $key;
|
||||
$options[ 'sync-' . $key ] = \IPS\Member::loggedIn()->language()->addToStack( 'member_photo_sync' , FALSE, array( 'sprintf' => array( \IPS\Member::loggedIn()->language()->addToStack( $langKey ) ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
/* And of course we can always not have a photo... except when we can't */
|
||||
$photoRequired = FALSE;
|
||||
foreach( \IPS\Member\ProfileStep::loadAll() AS $step )
|
||||
@@ -1097,7 +1186,6 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $photoRequired === FALSE )
|
||||
{
|
||||
$options['none'] = 'member_photo_none';
|
||||
@@ -1116,7 +1204,6 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
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 ), function( $val ) {
|
||||
|
||||
if ( $val instanceof \IPS\File )
|
||||
{
|
||||
$image = \IPS\Image::create( $val->contents() );
|
||||
@@ -1128,7 +1215,16 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
}, NULL, NULL, 'member_photo_upload' ) );
|
||||
|
||||
/* Create the URL */
|
||||
$form->add( new \IPS\Helpers\Form\Url( 'member_photo_url', NULL, FALSE, array( 'file' => 'core_Profile', 'image' => TRUE, 'maxFileSize' => $photoVars[0] ? $photoVars[0] / 1024 : NULL, 'maxDimensions' => array( 'width' => $photoVars[1], 'height' => $photoVars[2] ) ), NULL, NULL, NULL, 'member_photo_url' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Url( 'member_photo_url', NULL, FALSE, array( 'file' => 'core_Profile', 'image' => TRUE, 'maxFileSize' => $photoVars[0] ? $photoVars[0] / 1024 : NULL, 'maxDimensions' => array( 'width' => $photoVars[1], 'height' => $photoVars[2] ) ), function( $val ) {
|
||||
if ( $val instanceof \IPS\Http\Url )
|
||||
{
|
||||
$image = \IPS\Image::create( (string) $val->request()->get() );
|
||||
if( $image->isAnimatedGif and !$this->member->group['g_upload_animated_photos'] )
|
||||
{
|
||||
throw new \DomainException('member_photo_upload_no_animated');
|
||||
}
|
||||
}
|
||||
}, NULL, NULL, 'member_photo_url' ) );
|
||||
}
|
||||
|
||||
/* Add additional elements */
|
||||
@@ -1142,16 +1238,12 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
{
|
||||
$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 ) )
|
||||
/* Disable syncing */
|
||||
$profileSync = $this->member->profilesync;
|
||||
if ( isset( $profileSync['photo'] ) )
|
||||
{
|
||||
foreach( $services AS $class )
|
||||
{
|
||||
$obj = new $class( $this->member );
|
||||
$obj->save( array( 'profilesync_photo' => FALSE ) );
|
||||
}
|
||||
unset( $profileSync['photo'] );
|
||||
$this->member->profilesync = $profileSync;
|
||||
}
|
||||
|
||||
switch ( $values['pp_photo_type'] )
|
||||
@@ -1197,14 +1289,6 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
case 'gravatar':
|
||||
$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:
|
||||
if ( mb_substr( $values['pp_photo_type'], 0, 5 ) === 'sync-' )
|
||||
{
|
||||
$class = 'IPS\core\ProfileSync\\' . mb_substr( $values['pp_photo_type'], 5 );
|
||||
$obj = new $class( $this->member );
|
||||
$obj->save( array( 'profilesync_photo' => TRUE ) );
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset Profile Complete flag in case this was an optional step */
|
||||
@@ -1212,6 +1296,15 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
|
||||
$this->member->save();
|
||||
|
||||
if ( $this->member->pp_photo_type )
|
||||
{
|
||||
$this->member->logHistory( 'core', 'photo', array( 'action' => 'new', 'type' => $this->member->pp_photo_type ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->member->logHistory( 'core', 'photo', array( 'action' => 'remove' ) );
|
||||
}
|
||||
|
||||
if ( $this->member->pp_photo_type == 'custom' )
|
||||
{
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
@@ -1270,8 +1363,17 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
}
|
||||
|
||||
/* Get the photo */
|
||||
$original = \IPS\File::get( 'core_Profile', $this->member->pp_main_photo );
|
||||
$image = \IPS\Image::create( $original->contents() );
|
||||
try
|
||||
{
|
||||
$original = \IPS\File::get( 'core_Profile', $this->member->pp_main_photo );
|
||||
$image = \IPS\Image::create( $original->contents() );
|
||||
}
|
||||
catch( \Exception $e )
|
||||
{
|
||||
\IPS\Log::log( $e, 'crop_error' );
|
||||
|
||||
\IPS\Output::i()->error( 'no_photo_to_crop', '3C138/N', 404, '' );
|
||||
}
|
||||
|
||||
/* Work out which dimensions to suggest */
|
||||
if ( $image->width < $image->height )
|
||||
@@ -1290,7 +1392,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
$form->add( new \IPS\Helpers\Form\Custom('photo_crop', array( 0, 0, $suggestedWidth, $suggestedHeight ), FALSE, array(
|
||||
'getHtml' => function( $field ) use ( $original, $member )
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate('profile')->photoCrop( $field->name, $field->value, $member->url()->setQueryString( 'do', 'cropPhotoGetPhoto' )->csrf() );
|
||||
return \IPS\Theme::i()->getTemplate('members', 'core', 'global')->photoCrop( $field->name, $field->value, $member->url()->setQueryString( 'do', 'cropPhotoGetPhoto' )->csrf() );
|
||||
}
|
||||
) ) );
|
||||
|
||||
@@ -1328,7 +1430,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
$form->error = 'photo_crop_bad';
|
||||
$form->error = \IPS\Member::loggedIn()->language()->addToStack('photo_crop_bad');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1485,7 +1587,10 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
$tabs['all'] = \IPS\Member::loggedIn()->language()->addToStack('all');
|
||||
foreach( \IPS\Content\Reaction::roots() AS $reaction )
|
||||
{
|
||||
$tabs[ $reaction->id ] = $reaction->_title;
|
||||
if ($reaction->_enabled !== FALSE)
|
||||
{
|
||||
$tabs[$reaction->id] = $reaction->_title;
|
||||
}
|
||||
}
|
||||
|
||||
$activeTab = 'all';
|
||||
@@ -1537,7 +1642,7 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
|
||||
if ( $canReport !== TRUE )
|
||||
{
|
||||
\IPS\Output::i()->error( 'generic_error', '1C138/6', 403, '' );
|
||||
\IPS\Output::i()->error( $canReport, '1C138/6', 403, '' );
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form( NULL, 'report_submit' );
|
||||
@@ -1613,23 +1718,17 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
* Set Cover Photo
|
||||
*
|
||||
* @param \IPS\Helpers\CoverPhoto $photo New Photo
|
||||
* @param string $type 'new', 'remove', 'reposition'
|
||||
* @return void
|
||||
*/
|
||||
protected function _coverPhotoSet( \IPS\Helpers\CoverPhoto $photo )
|
||||
protected function _coverPhotoSet( \IPS\Helpers\CoverPhoto $photo, $type=NULL )
|
||||
{
|
||||
/* 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 ) )
|
||||
/* Disable syncing */
|
||||
$profileSync = $this->member->profilesync;
|
||||
if ( isset( $profileSync['cover'] ) )
|
||||
{
|
||||
foreach( $services AS $class )
|
||||
{
|
||||
$obj = new $class( $this->member );
|
||||
if ( $obj->connected() )
|
||||
{
|
||||
$obj->save( array( 'profilesync_cover' => FALSE ) );
|
||||
}
|
||||
}
|
||||
unset( $profileSync['cover'] );
|
||||
$this->member->profilesync = $profileSync;
|
||||
}
|
||||
|
||||
$this->member->pp_cover_photo = (string) $photo->file;
|
||||
@@ -1639,6 +1738,10 @@ class _profile extends \IPS\Helpers\CoverPhoto\Controller
|
||||
$this->member->members_bitoptions['profile_completed'] = FALSE;
|
||||
|
||||
$this->member->save();
|
||||
if ( $type != 'reposition' )
|
||||
{
|
||||
$this->member->logHistory( 'core', 'coverphoto', array( 'action' => $type ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -232,9 +232,9 @@ class _messenger extends \IPS\Content\Controller
|
||||
{
|
||||
$where[] = array( 'core_message_topic_user_map.map_has_unread=1' );
|
||||
}
|
||||
|
||||
/* Add a folder filter */
|
||||
if ( isset( \IPS\Request::i()->folder ) or !is_null( $folder ) )
|
||||
|
||||
/* Add a folder filter, if we are not coming from the Messages menu */
|
||||
if ( !isset( \IPS\Request::i()->_fromMenu ) )
|
||||
{
|
||||
if ( !is_null( $folder ) AND isset( $folders[ $folder ] ) )
|
||||
{
|
||||
@@ -252,6 +252,9 @@ class _messenger extends \IPS\Content\Controller
|
||||
|
||||
if ( \IPS\Request::i()->q )
|
||||
{
|
||||
/* Limit result set to prevent time outs */
|
||||
$where[] = array( 'core_message_topic_user_map.map_last_topic_reply > ?', \IPS\DateTime::ts( time() )->sub( new \DateInterval( 'P1Y' ) )->getTimeStamp() );
|
||||
|
||||
$subQuery = \IPS\Db::i()->select( 'map_topic_id', array( 'core_message_topic_user_map', 'core_message_topic_user_map' ), $where );
|
||||
$where = array( array( 'core_message_posts.msg_topic_id IN (?)', $subQuery ) );
|
||||
$query = array();
|
||||
@@ -283,7 +286,7 @@ class _messenger extends \IPS\Content\Controller
|
||||
/* Get a count */
|
||||
try
|
||||
{
|
||||
$count = \IPS\Db::i()->select( 'COUNT(*)', 'core_message_posts', $where, NULL, NULL, 'msg_topic_id' )
|
||||
$count = \IPS\Db::i()->select( 'COUNT( DISTINCT(msg_topic_id) )', 'core_message_posts', array_merge( $where, array( array( 'core_message_topic_user_map.map_last_topic_reply > ?', \IPS\DateTime::ts( time() )->sub( new \DateInterval( 'P1Y' ) )->getTimeStamp() ) ) ) )
|
||||
->join(
|
||||
'core_message_topics',
|
||||
'core_message_posts.msg_topic_id=core_message_topics.mt_id'
|
||||
@@ -416,10 +419,17 @@ class _messenger extends \IPS\Content\Controller
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('messaging')->conversation( $conversation, $folders );
|
||||
}
|
||||
elseif( \IPS\Request::i()->q )
|
||||
{
|
||||
\IPS\Output::i()->json( array(
|
||||
'data' => \IPS\Theme::i()->getTemplate('messaging')->messageListRows( $conversations, $pagination, FALSE, $folders ),
|
||||
'pagination' => $pagination
|
||||
) );
|
||||
}
|
||||
elseif( \IPS\Request::i()->overview )
|
||||
{
|
||||
\IPS\Output::i()->json( array(
|
||||
'data' => \IPS\Theme::i()->getTemplate('messaging')->messageListRows( $conversations, $pagination, TRUE, $folders ),
|
||||
'data' => \IPS\Theme::i()->getTemplate('messaging')->messageListRows( $conversations, $pagination, \IPS\Request::i()->_fromMenu ? FALSE : TRUE, $folders ),
|
||||
'pagination' => $pagination,
|
||||
'listBaseUrl' => $listUrl->setQueryString( array( 'sortBy' => \IPS\Request::i()->sortBy, 'filter' => \IPS\Request::i()->filter ) )->stripQueryString( 'id' )
|
||||
) );
|
||||
@@ -431,7 +441,7 @@ class _messenger extends \IPS\Content\Controller
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('messaging')->template( $folder, $folders, $folderCounts, $conversations, $pagination, $conversation, $baseUrl, ( $conversation ? 'messenger_convo' : 'messenger' ), ( \IPS\Request::i()->sortBy ? htmlspecialchars( \IPS\Request::i()->sortBy, ENT_QUOTES | \IPS\HTMLENTITIES, 'UTF-8', FALSE ): 'mt_last_post_time' ), ( \IPS\Request::i()->filter ? htmlspecialchars( \IPS\Request::i()->filter, ENT_QUOTES | \IPS\HTMLENTITIES, 'UTF-8', FALSE ) : '' ) );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('messaging')->template( $folder, $folders, $folderCounts, $conversations, $pagination, $conversation, $baseUrl, ( $conversation ? 'messenger_convo' : 'messenger' ), ( \IPS\Request::i()->sortBy ? htmlspecialchars( \IPS\Request::i()->sortBy, ENT_QUOTES | ENT_DISALLOWED, 'UTF-8', FALSE ): 'mt_last_post_time' ), ( \IPS\Request::i()->filter ? htmlspecialchars( \IPS\Request::i()->filter, ENT_QUOTES | ENT_DISALLOWED, 'UTF-8', FALSE ) : '' ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -459,8 +469,13 @@ class _messenger extends \IPS\Content\Controller
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
$folders = json_decode( \IPS\Member::loggedIn()->pconversation_filters, TRUE );
|
||||
array_walk( $folders, function( &$val )
|
||||
{
|
||||
$val = htmlspecialchars( $val, ENT_DISALLOWED | ENT_QUOTES, 'UTF-8' );
|
||||
} );
|
||||
|
||||
$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 ) ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Select( 'move_message_to', NULL, FALSE, array( 'options' => array_merge( array( 'myconvo' => \IPS\Member::loggedIn()->language()->addToStack('inbox') ), $folders ), 'parse' => 'normal' ) ) );
|
||||
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
@@ -742,6 +757,7 @@ class _messenger extends \IPS\Content\Controller
|
||||
$ids[] = $member->member_id;
|
||||
|
||||
$notification = new \IPS\Notification( \IPS\Application::load('core'), 'private_message_added', $conversation, array( $conversation, \IPS\Member::loggedIn() ) );
|
||||
$notification->recipients->attach( $member );
|
||||
$notification->send();
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,35 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
*/
|
||||
class _modcp extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* Dispatcher looks for methods to match do param, which may exist in the extension files, so this method
|
||||
* prevents dispatcher throwing a 2S106/1 and allows the extensions to use the values
|
||||
*
|
||||
* @param string $method Desired method
|
||||
* @param array $args Arguments
|
||||
* @return void
|
||||
*/
|
||||
public function __call( $method, $args )
|
||||
{
|
||||
if ( isset( \IPS\Request::i()->do ) )
|
||||
{
|
||||
$activeTab = \IPS\Request::i()->tab ?: 'overview';
|
||||
foreach ( \IPS\Application::allExtensions( 'core', 'ModCp', TRUE ) as $key => $extension )
|
||||
{
|
||||
if( method_exists( $extension, 'getTab' ) and mb_strtolower( $extension->getTab() ) == mb_strtolower( $activeTab ) )
|
||||
{
|
||||
if ( method_exists( $extension, \IPS\Request::i()->do ) )
|
||||
{
|
||||
return $this->manage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Still here? */
|
||||
\IPS\Output::i()->error( 'page_not_found', '2C139/5', 404, '' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Moderator Control Panel
|
||||
*
|
||||
@@ -45,6 +74,9 @@ class _modcp extends \IPS\Dispatcher\Controller
|
||||
$activeTab = \IPS\Request::i()->tab ?: 'overview';
|
||||
$tabs = array( 'reports' => array(), 'approval' => array() );
|
||||
$content = '';
|
||||
|
||||
$approvalQueueCount = 0;
|
||||
|
||||
foreach ( \IPS\Application::allExtensions( 'core', 'ModCp', TRUE ) as $key => $extension )
|
||||
{
|
||||
if( method_exists( $extension, 'getTab' ) )
|
||||
@@ -55,6 +87,12 @@ class _modcp extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$tabs[ $tab ][] = $key;
|
||||
}
|
||||
|
||||
/* Get the count for the approval queue from the extension */
|
||||
if( $tab == 'approval' )
|
||||
{
|
||||
$approvalQueueCount = $extension->getApprovalQueueCount( false );
|
||||
}
|
||||
}
|
||||
|
||||
if( mb_strtolower( $extension->getTab() ) == mb_strtolower( $activeTab ) )
|
||||
@@ -113,22 +151,6 @@ 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();
|
||||
if ( \IPS\Settings::i()->clubs and \IPS\Settings::i()->clubs_require_approval and \IPS\Member::loggedIn()->modPermission('can_access_all_clubs') )
|
||||
{
|
||||
$approvalQueueCount += \IPS\Db::i()->select( 'COUNT(*)', 'core_clubs', 'approved=0' )->first();
|
||||
}
|
||||
\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' ) );
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/modcp_responsive.css' ) );
|
||||
|
||||
@@ -36,76 +36,43 @@ 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 */
|
||||
$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() )
|
||||
{
|
||||
$subWhere[] = array( "s.login_type!=?", \IPS\Session\Front::LOGIN_TYPE_ANONYMOUS );
|
||||
}
|
||||
|
||||
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 = new \IPS\core\Online\Table( \IPS\Http\Url::internal( 'app=core&module=online&controller=online', 'front', 'online' ) );
|
||||
$table->tableTemplate = array( \IPS\Theme::i()->getTemplate( 'online', 'core', 'front' ), 'onlineUsersTable' );
|
||||
$table->rowsTemplate = array( \IPS\Theme::i()->getTemplate( 'online', 'core', 'front' ), 'onlineUsersRow' );
|
||||
$table->langPrefix = 'online_users_';
|
||||
$table->include = array( 'photo', 'member_name', 'location_lang', 'running_time', 'ip_address', 'login_type' );
|
||||
$table->limit = 30;
|
||||
$table->noSort = array( 'photo', 'location_lang' );
|
||||
|
||||
/* Custom parsers */
|
||||
$table->parsers = array(
|
||||
'location_lang' => function( $val, $row )
|
||||
'location_lang' => function( $val, $row )
|
||||
{
|
||||
return \IPS\Session\Front::getLocation( $row );
|
||||
},
|
||||
'photo' => function( $val, $row )
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate( 'global', 'core' )->userPhoto( \IPS\Member::load( $row['member_id'] ), 'mini' );
|
||||
},
|
||||
'running_time' => function( $val, $row )
|
||||
{
|
||||
return \IPS\DateTime::ts( $val )->relative();
|
||||
},
|
||||
'member_name' => function( $val, $row )
|
||||
{
|
||||
if( $row['member_id'] )
|
||||
{
|
||||
return \IPS\Session\Front::getLocation( $row );
|
||||
},
|
||||
'photo' => function( $val, $row )
|
||||
return \IPS\Theme::i()->getTemplate( 'global', 'core' )->userLink( \IPS\Member::load( $row['member_id'] ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate( 'global', 'core' )->userPhoto( \IPS\Member::load( $row['member_id'] ), 'mini' );
|
||||
},
|
||||
'running_time' => function( $val, $row )
|
||||
{
|
||||
return \IPS\DateTime::ts( $val )->relative();
|
||||
},
|
||||
'member_name' => function( $val, $row )
|
||||
{
|
||||
if( $row['member_id'] )
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate( 'global', 'core' )->userLink( \IPS\Member::load( $row['member_id'] ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return \IPS\Member::loggedIn()->language()->addToStack( 'guest' );
|
||||
}
|
||||
},
|
||||
return \IPS\Member::loggedIn()->language()->addToStack( 'guest' );
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
$table->filters = array(
|
||||
'filter_loggedin' => 'core_sessions.member_id <> 0',
|
||||
'filter_loggedin' => 'filter_loggedin',
|
||||
);
|
||||
|
||||
foreach ( \IPS\Member\Group::groups( TRUE, TRUE, TRUE ) as $group )
|
||||
@@ -123,29 +90,18 @@ class _online extends \IPS\Dispatcher\Controller
|
||||
|
||||
if( $group->g_id == \IPS\Settings::i()->guest_group )
|
||||
{
|
||||
$table->filters[ 'group_' . $group->g_id ] = 'core_sessions.member_id IS NULL';
|
||||
$table->filters[ 'group_' . $group->g_id ] = $group->g_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
$table->filters[ 'group_' . $group->g_id ] = 'core_sessions.member_group=' . $group->g_id;
|
||||
$table->filters[ 'group_' . $group->g_id ] = $group->g_id;
|
||||
}
|
||||
}
|
||||
|
||||
$table->sortBy = $table->sortBy ?: 'running_time';
|
||||
$table->sortDirection = $table->sortDirection ?: 'desc';
|
||||
|
||||
/* Get the count */
|
||||
$counter = \IPS\Db::i()->select( 'COUNT(*)', 'core_sessions', $where );
|
||||
|
||||
foreach( $table->joins as $join )
|
||||
{
|
||||
$counter = $counter->join( $join['from'], $join['where'] );
|
||||
}
|
||||
|
||||
$totalCount = $counter->first();
|
||||
|
||||
/* Display */
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('online_users');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'online', 'core', 'front' )->onlineUsersList( (string) $table, $totalCount );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'online', 'core', 'front' )->onlineUsersList( (string) $table, $table->count );
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,11 @@ class _promote extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->error( 'page_not_found', '2C356/5', 404, '' );
|
||||
}
|
||||
|
||||
if ( ! \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'promotion', 'promote_manage' ) and $promote->added_by != \IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C366/2', 403, '' );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$object = $class::load( $id );
|
||||
@@ -57,13 +62,87 @@ class _promote extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->error( 'page_not_found', '2C356/7', 404, '' );
|
||||
}
|
||||
|
||||
$title = NULL;
|
||||
$settings = $promote->form_data;
|
||||
|
||||
if ( ! empty( $settings['internal']['title'] ) )
|
||||
{
|
||||
$title = $settings['internal']['title'];
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form( 'form', 'save' );
|
||||
$form->class = 'ipsForm_vertical cPromoteDialog';
|
||||
$form->attributes = array( 'data-controller' => 'core.front.system.promote' );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'promote_social_title_internal', $title, FALSE ) );
|
||||
$form->add( new \IPS\Helpers\Form\TextArea( 'promote_internal_text', $promote->getText('internal'), FALSE, array( 'rows' => 10 ) ) );
|
||||
|
||||
/* Existing media */
|
||||
try
|
||||
{
|
||||
if ( $images = $object->contentImages( 20 ) )
|
||||
{
|
||||
$form->addHtml( \IPS\Theme::i()->getTemplate( 'promote' )->promoteDialogImages( $images, $promote ) );
|
||||
}
|
||||
}
|
||||
catch( \BadMethodCallException $e ) { }
|
||||
|
||||
/* Upload box */
|
||||
$existingMedia = array();
|
||||
if ( $promote )
|
||||
{
|
||||
foreach( $promote->media as $file )
|
||||
{
|
||||
try
|
||||
{
|
||||
$existingMedia[] = \IPS\File::get( 'core_Promote', $file );
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
}
|
||||
}
|
||||
|
||||
$uploader = new \IPS\Helpers\Form\Upload( 'promote_media', $existingMedia, FALSE, array(
|
||||
'multiple' => TRUE,
|
||||
'storageExtension' => 'core_Promote',
|
||||
'maxFiles' => 10,
|
||||
'image' => TRUE,
|
||||
'maxFileSize' => 3,
|
||||
) );
|
||||
|
||||
$form->add( $uploader );
|
||||
|
||||
/* Saving? */
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
/* Content images */
|
||||
$saveImages = array();
|
||||
if ( $images )
|
||||
{
|
||||
foreach( $images as $image )
|
||||
{
|
||||
foreach( $image as $extension => $path )
|
||||
{
|
||||
if ( \IPS\Request::i()->attach_files and in_array( $path, array_keys( \IPS\Request::i()->attach_files ) ) )
|
||||
{
|
||||
$saveImages[] = array( $extension => $path );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$media = array();
|
||||
if ( is_array( $values['promote_media'] ) )
|
||||
{
|
||||
foreach( $values['promote_media'] as $key => $file )
|
||||
{
|
||||
$media[] = (string) $file;
|
||||
}
|
||||
}
|
||||
|
||||
$settings['internal']['title'] = $values['promote_social_title_internal'];
|
||||
|
||||
$promote->images = $saveImages;
|
||||
$promote->media = $media;
|
||||
$promote->form_data = $settings;
|
||||
$promote->setText( 'internal', $values['promote_internal_text'] );
|
||||
$promote->save();
|
||||
|
||||
@@ -129,6 +208,11 @@ class _promote extends \IPS\Dispatcher\Controller
|
||||
/* Create the table */
|
||||
$table = new \IPS\core\Promote\Table( \IPS\Http\Url::internal( 'app=core&module=promote&controller=promote&do=view', 'front', 'promote_manage' ) );
|
||||
|
||||
if ( ! \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'promotion', 'promote_manage' ) )
|
||||
{
|
||||
$table->setMember( \IPS\Member::loggedIn() );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js('front_promote.js', 'core' ) );
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/promote.css' ) );
|
||||
|
||||
@@ -160,6 +244,12 @@ class _promote extends \IPS\Dispatcher\Controller
|
||||
try
|
||||
{
|
||||
$item = \IPS\core\Promote::load( \IPS\Request::i()->promote_id );
|
||||
|
||||
if ( ! \IPS\Member::loggedIn()->hasAcpRestriction( 'core', 'promotion', 'promote_manage' ) and $item->added_by != \IPS\Member::loggedIn()->member_id )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C366/1', 403, '' );
|
||||
}
|
||||
|
||||
$item->delete();
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=promote&controller=promote&do=view', 'front', 'promote_manage' ), 'promote_item_deleted' );
|
||||
@@ -228,6 +318,11 @@ class _promote extends \IPS\Dispatcher\Controller
|
||||
|
||||
try
|
||||
{
|
||||
if( !$class OR !class_exists( $class ) )
|
||||
{
|
||||
throw new \InvalidArgumentException;
|
||||
}
|
||||
|
||||
$object = $class::load( $id );
|
||||
}
|
||||
catch ( \Exception $ex )
|
||||
@@ -405,6 +500,8 @@ class _promote extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$text = array();
|
||||
$shareTo = array();
|
||||
$processedForms = array();
|
||||
|
||||
foreach( $services as $service )
|
||||
{
|
||||
$key = mb_strtolower( $service->key );
|
||||
@@ -413,9 +510,10 @@ class _promote extends \IPS\Dispatcher\Controller
|
||||
$text[ $key ] = $values[ 'promote_social_content_' . $key ];
|
||||
$shareTo[] = $key;
|
||||
}
|
||||
|
||||
$processedForms[ $key ] = $service->processPromoteForm( $values );
|
||||
}
|
||||
|
||||
|
||||
$media = array();
|
||||
if ( is_array( $values['promote_media'] ) )
|
||||
{
|
||||
@@ -481,6 +579,7 @@ class _promote extends \IPS\Dispatcher\Controller
|
||||
$promote->share_to = $shareTo;
|
||||
$promote->failed = 0; # Reset the failed flag if we're re-promoting
|
||||
$promote->sent = 0;
|
||||
$promote->form_data = $processedForms;
|
||||
$promote->save();
|
||||
|
||||
if ( isset( \IPS\Request::i()->promote_id ) )
|
||||
@@ -496,7 +595,7 @@ class _promote extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
else
|
||||
{
|
||||
$output = \IPS\Theme::i()->getTemplate( 'promote' )->promoteDialog( \IPS\Member::loggedIn()->language()->addToStack('promote_social_title'), $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'promote', 'core' ) ), 'promoteDialogTemplate' ) ), $existing, $object );
|
||||
$output = \IPS\Theme::i()->getTemplate( 'promote' )->promoteDialog( \IPS\Member::loggedIn()->language()->addToStack('promote_social_title'), $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'promote', 'core' ) ), 'promoteDialogTemplate' ), $existing, $object ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
$baseUrl = $baseUrl->setQueryString( 'tags', \IPS\Request::i()->tags );
|
||||
}
|
||||
|
||||
$types = $this->_contentTypes();
|
||||
$types = static::contentTypes();
|
||||
|
||||
/* Flood control */
|
||||
\IPS\Request::floodCheck();
|
||||
@@ -199,8 +199,16 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
|
||||
foreach( $groups as $_idx => $groupId )
|
||||
{
|
||||
if( \IPS\Member\Group::load( $groupId )->g_bitoptions['gbw_hide_group'] )
|
||||
try
|
||||
{
|
||||
if( \IPS\Member\Group::load( $groupId )->g_bitoptions['gbw_hide_group'] )
|
||||
{
|
||||
unset( $groups[ $_idx ] );
|
||||
}
|
||||
}
|
||||
catch( \OutOfRangeException $e )
|
||||
{
|
||||
/* Group didn't exist, so let's ignore it */
|
||||
unset( $groups[ $_idx ] );
|
||||
}
|
||||
}
|
||||
@@ -339,9 +347,10 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
/* Set content type */
|
||||
if ( isset( \IPS\Request::i()->type ) and array_key_exists( \IPS\Request::i()->type, $types ) )
|
||||
{
|
||||
$class = $types[ \IPS\Request::i()->type ];
|
||||
|
||||
if ( isset( \IPS\Request::i()->item ) )
|
||||
{
|
||||
$class = $types[ \IPS\Request::i()->type ];
|
||||
try
|
||||
{
|
||||
$item = $class::loadAndCheckPerms( \IPS\Request::i()->item );
|
||||
@@ -392,19 +401,19 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
$baseUrl = $baseUrl->setQueryString( 'search_min_comments', \IPS\Request::i()->search_min_comments );
|
||||
$titleConditions[] = \IPS\Member::loggedIn()->language()->addToStack( 'search_blurb_min_comments', FALSE, array( 'sprintf' => array( \IPS\Request::i()->search_min_comments ) ) );
|
||||
}
|
||||
if ( isset( \IPS\Request::i()->search_min_replies ) )
|
||||
if ( isset( \IPS\Request::i()->search_min_replies ) AND isset( $class::$commentClass ) )
|
||||
{
|
||||
$filter->minimumComments( \IPS\Request::i()->search_min_replies + 1 );
|
||||
$baseUrl = $baseUrl->setQueryString( 'search_min_replies', \IPS\Request::i()->search_min_replies );
|
||||
$titleConditions[] = \IPS\Member::loggedIn()->language()->addToStack( 'search_blurb_min_replies', FALSE, array( 'sprintf' => array( \IPS\Request::i()->search_min_replies ) ) );
|
||||
}
|
||||
if ( isset( \IPS\Request::i()->search_min_reviews ) )
|
||||
if ( isset( \IPS\Request::i()->search_min_reviews ) AND isset( $class::$reviewClass ) )
|
||||
{
|
||||
$filter->minimumReviews( \IPS\Request::i()->search_min_reviews );
|
||||
$baseUrl = $baseUrl->setQueryString( 'search_min_reviews', \IPS\Request::i()->search_min_reviews );
|
||||
$titleConditions[] = \IPS\Member::loggedIn()->language()->addToStack( 'search_blurb_min_reviews', FALSE, array( 'sprintf' => array( \IPS\Request::i()->search_min_reviews ) ) );
|
||||
}
|
||||
if ( isset( \IPS\Request::i()->search_min_views ) )
|
||||
if ( isset( \IPS\Request::i()->search_min_views ) AND isset( $class::$databaseColumnMap['views'] ) )
|
||||
{
|
||||
$filter->minimumViews( \IPS\Request::i()->search_min_views );
|
||||
$baseUrl = $baseUrl->setQueryString( 'search_min_views', \IPS\Request::i()->search_min_views );
|
||||
@@ -429,7 +438,7 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/* Filter by club */
|
||||
if ( isset( \IPS\Request::i()->club ) )
|
||||
if ( isset( \IPS\Request::i()->club ) AND \IPS\Settings::i()->clubs )
|
||||
{
|
||||
$clubIds = array();
|
||||
$clubNames = array();
|
||||
@@ -521,12 +530,16 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
|
||||
$tagList = array_map( function( $val )
|
||||
{
|
||||
return '\'' . htmlentities( $val, \IPS\HTMLENTITIES | ENT_QUOTES, 'UTF-8', FALSE ) . '\'';
|
||||
return '\'' . htmlentities( $val, ENT_DISALLOWED | ENT_QUOTES, 'UTF-8', FALSE ) . '\'';
|
||||
}, explode( ',', \IPS\Request::i()->tags ) );
|
||||
}
|
||||
$title = '';
|
||||
if ( \IPS\Request::i()->q )
|
||||
{
|
||||
\IPS\core\Facebook\Pixel::i()->Search = array(
|
||||
'search_string' => \IPS\Request::i()->q
|
||||
);
|
||||
|
||||
if ( \IPS\Request::i()->tags )
|
||||
{
|
||||
if ( isset( \IPS\Request::i()->eitherTermsOrTags ) and \IPS\Request::i()->eitherTermsOrTags === 'and' )
|
||||
@@ -588,10 +601,11 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
$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' )
|
||||
$operator = NULL;
|
||||
|
||||
if ( isset( \IPS\Request::i()->search_and_or ) and in_array( \IPS\Request::i()->search_and_or, array( \IPS\Content\Search\Query::OPERATOR_OR, \IPS\Content\Search\Query::OPERATOR_AND ) ) )
|
||||
{
|
||||
$flags = $flags | \IPS\Content\Search\Query::TERM_OR_MODE;
|
||||
$operator = \IPS\Request::i()->search_and_or;
|
||||
$baseUrl = $baseUrl->setQueryString( 'search_and_or', \IPS\Request::i()->search_and_or );
|
||||
}
|
||||
|
||||
@@ -605,7 +619,8 @@ 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 + \IPS\Content\Search\Query::TAGS_MATCH_ITEMS_ONLY
|
||||
$flags + \IPS\Content\Search\Query::TAGS_MATCH_ITEMS_ONLY,
|
||||
$operator
|
||||
);
|
||||
|
||||
/* Get pagination */
|
||||
@@ -622,7 +637,7 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/* 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 ) );
|
||||
\IPS\Output::i()->redirect( $baseUrl->setQueryString( 'page', 1 ), NULL, 303 );
|
||||
}
|
||||
|
||||
$pagination = trim( \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->pagination( $baseUrl, $pages, $page, $query->resultsToGet ) );
|
||||
@@ -690,7 +705,7 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Types */
|
||||
$types = array( '' => 'search_everything' );
|
||||
$contentTypes = $this->_contentTypes();
|
||||
$contentTypes = static::contentTypes();
|
||||
$contentToggles = array();
|
||||
$typeFields = array();
|
||||
$typeFieldToggles = array('' => array( 'club' ) );
|
||||
@@ -742,7 +757,13 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
$types[ $k ] = $k . '_pl';
|
||||
if ( $k !== 'core_members' )
|
||||
{
|
||||
$typeFieldToggles[ $k ] = array_merge( $contentToggles, array( $k . '_node', 'search_min_views' ) );
|
||||
$typeFieldToggles[ $k ][] = $k . '_node';
|
||||
|
||||
if( isset( $class::$databaseColumnMap['views'] ) )
|
||||
{
|
||||
$typeFieldToggles[ $k ][] = 'search_min_views';
|
||||
}
|
||||
|
||||
if ( isset( $class::$commentClass ) )
|
||||
{
|
||||
if ( $class::$firstCommentRequired )
|
||||
@@ -768,23 +789,26 @@ 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' => TRUE ), NULL, NULL, NULL, 'tags' ), NULL, 'search_tab_content' );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'tags', \IPS\Request::i()->tags, FALSE, array( 'autocomplete' => array( 'minimized' => FALSE ) ), 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 */
|
||||
$form->add( new \IPS\Helpers\Form\Member( 'author', NULL, FALSE, array(), NULL, NULL, NULL, 'author' ), NULL, 'search_tab_content' );
|
||||
|
||||
/* Club */
|
||||
$clubs = \IPS\Member\Club::clubs( \IPS\Member::loggedIn(), NULL, 'name', TRUE );
|
||||
if ( count( $clubs ) )
|
||||
if( \IPS\Settings::i()->clubs )
|
||||
{
|
||||
$clubOptions = array();
|
||||
foreach ( $clubs as $club )
|
||||
$clubs = \IPS\Member\Club::clubs( \IPS\Member::loggedIn(), NULL, 'name', TRUE );
|
||||
if ( is_object( $clubs ) AND $clubs->count( TRUE ) )
|
||||
{
|
||||
$clubOptions[ "c{$club->id}" ] = $club->name;
|
||||
$clubOptions = array();
|
||||
foreach ( $clubs as $club )
|
||||
{
|
||||
$clubOptions[ "c{$club->id}" ] = $club->name;
|
||||
}
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Select( 'club', NULL, FALSE, array( 'options' => $clubOptions, 'parse' => 'normal', 'multiple' => TRUE, 'noDefault' => TRUE, 'class' => 'ipsField_fullWidth' ), NULL, NULL, NULL, 'club' ), NULL, 'search_tab_content' );
|
||||
}
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Select( 'club', NULL, FALSE, array( 'options' => $clubOptions, 'parse' => 'normal', 'multiple' => TRUE, 'noDefault' => TRUE, 'class' => 'ipsContained' ), NULL, NULL, NULL, 'club' ), NULL, 'search_tab_content' );
|
||||
}
|
||||
|
||||
/* Dates */
|
||||
@@ -795,15 +819,29 @@ 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' );
|
||||
$form->add( new \IPS\Helpers\Form\Radio( 'search_and_or', isset( \IPS\Request::i()->search_and_or ) ? \IPS\Request::i()->search_and_or : \IPS\Settings::i()->search_default_operator, 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 ) )
|
||||
{
|
||||
$nodes = NULL;
|
||||
|
||||
/* If we have a node type, we should only select nodes for that type */
|
||||
if( isset( \IPS\Request::i()->type ) AND !empty( \IPS\Request::i()->type ) )
|
||||
{
|
||||
$typeInfo = explode( '_', \IPS\Request::i()->type );
|
||||
$typeClass = 'IPS\\' . $typeInfo[0] . '\\' . mb_ucfirst( $typeInfo[1] );
|
||||
|
||||
if( $typeClass == $class )
|
||||
{
|
||||
$nodes = ( isset( \IPS\Request::i()->nodes ) ) ? \IPS\Request::i()->nodes : NULL;
|
||||
}
|
||||
}
|
||||
|
||||
$nodeClass = $class::$containerNodeClass;
|
||||
$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, 'clubs' => \IPS\IPS::classUsesTrait( $nodeClass, 'IPS\Content\ClubContainer' ) ), NULL, NULL, NULL, $k . '_node' );
|
||||
$field = new \IPS\Helpers\Form\Node( $k . '_node', $nodes, FALSE, array( 'class' => $nodeClass, 'subnodes' => FALSE, 'multiple' => TRUE, 'permissionCheck' => $nodeClass::searchableNodesPermission(), 'forceOwner' => FALSE, 'clubs' => ( \IPS\Settings::i()->clubs AND \IPS\IPS::classUsesTrait( $nodeClass, 'IPS\Content\ClubContainer' ) ) ), NULL, NULL, NULL, $k . '_node' );
|
||||
$field->label = \IPS\Member::loggedIn()->language()->addToStack( $nodeClass::$nodeTitle );
|
||||
$form->add( $field, NULL, 'search_tab_nodes' );
|
||||
}
|
||||
@@ -1018,12 +1056,57 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle quicksearch and redirect to correct results page
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function quicksearch()
|
||||
{
|
||||
$query = array();
|
||||
|
||||
if ( \IPS\Request::i()->q )
|
||||
{
|
||||
$query['q'] = \IPS\Request::i()->q;
|
||||
|
||||
if ( \IPS\Request::i()->type != 'all' )
|
||||
{
|
||||
if ( mb_substr( \IPS\Request::i()->type, 0, 11 ) === 'contextual_' )
|
||||
{
|
||||
if ( $json = json_decode( mb_substr( \IPS\Request::i()->type, 11 ), TRUE ) )
|
||||
{
|
||||
foreach ( $json as $k => $v )
|
||||
{
|
||||
$query[ $k ] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$query['type'] = \IPS\Request::i()->type;
|
||||
}
|
||||
}
|
||||
|
||||
if ( \IPS\Request::i()->search_and_or != \IPS\Settings::i()->search_default_operator )
|
||||
{
|
||||
$query['search_and_or'] = \IPS\Request::i()->search_and_or;
|
||||
}
|
||||
|
||||
if ( \IPS\Request::i()->search_in == 'titles' )
|
||||
{
|
||||
$query['search_in'] = 'titles';
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=search&controller=search', 'front', 'search' )->setQueryString( $query ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the different content type extensions
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function _contentTypes()
|
||||
public static function contentTypes()
|
||||
{
|
||||
$types = array();
|
||||
foreach ( \IPS\Content::routedClasses( TRUE, FALSE, TRUE ) as $class )
|
||||
@@ -1039,7 +1122,7 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
|
||||
/**
|
||||
* Splits the search term into distinct matches
|
||||
* e.g. one "two three" beccomes ['one', 'two three']
|
||||
* e.g. one "two three" becomes ['one', 'two three']
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@@ -1050,10 +1133,12 @@ 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);
|
||||
|
||||
$words = \IPS\Content\Search\Index::i()->stemmedTerms( $words );
|
||||
|
||||
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
|
||||
$words[ $idx ] = htmlentities( $word, ENT_DISALLOWED | 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 );
|
||||
@@ -1066,6 +1151,6 @@ class _search extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function globalFilterOptions()
|
||||
{
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'search' )->globalSearchMenuOptions( \IPS\Request::i()->checked ) );
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'search' )->globalSearchMenuOptions( explode( ',', \IPS\Request::i()->exclude ) ) );
|
||||
}
|
||||
}
|
||||
@@ -56,8 +56,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 | 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,
|
||||
'name' => \IPS\Dispatcher::i()->controllerLocation == 'admin' ? $member->group['prefix'] . htmlspecialchars( $member->name, ENT_DISALLOWED | ENT_QUOTES, 'UTF-8', FALSE ) . $member->group['suffix'] : htmlspecialchars( $member->name, ENT_DISALLOWED | ENT_QUOTES, 'UTF-8', FALSE ),
|
||||
'extra' => \IPS\Dispatcher::i()->controllerLocation == 'admin' ? htmlspecialchars( $member->email, ENT_DISALLOWED | ENT_QUOTES, 'UTF-8', FALSE ) : $member->groupName,
|
||||
'photo' => (string) $member->photo,
|
||||
);
|
||||
}
|
||||
@@ -342,9 +342,9 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
|
||||
$return['notifications']['data'][] = array(
|
||||
'id' => $notification->id,
|
||||
'title' => htmlspecialchars( $data['title'], \IPS\HTMLENTITIES | ENT_QUOTES, 'UTF-8', FALSE ),
|
||||
'title' => htmlspecialchars( $data['title'], ENT_DISALLOWED | ENT_QUOTES, 'UTF-8', FALSE ),
|
||||
'url' => (string) $data['url'],
|
||||
'content' => isset( $data['content'] ) ? htmlspecialchars( $data['content'], \IPS\HTMLENTITIES, 'UTF-8', FALSE ) : NULL,
|
||||
'content' => isset( $data['content'] ) ? htmlspecialchars( $data['content'], ENT_DISALLOWED, 'UTF-8', FALSE ) : NULL,
|
||||
'date' => $notification->updated_time->getTimestamp(),
|
||||
'author_photo' => $data['author'] ? $data['author']->photo : NULL
|
||||
);
|
||||
@@ -360,17 +360,24 @@ class _ajax extends \IPS\Dispatcher\Controller
|
||||
|
||||
foreach ( \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', $messagesDifference ) as $conversationId )
|
||||
{
|
||||
$conversation = \IPS\core\Messenger\Conversation::load( $conversationId );
|
||||
$message = $conversation->comments( 1, 0, 'date', 'desc' );
|
||||
|
||||
$return['messages']['data'][] = array(
|
||||
'id' => $conversation->id,
|
||||
'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'),
|
||||
'author_photo' => (string) $message->author()->photo
|
||||
);
|
||||
$conversation = \IPS\core\Messenger\Conversation::load( $conversationId );
|
||||
$message = $conversation->comments( 1, 0, 'date', 'desc' );
|
||||
|
||||
if( $message )
|
||||
{
|
||||
$return['messages']['data'][] = array(
|
||||
'id' => $conversation->id,
|
||||
'title' => htmlspecialchars( $conversation->title, ENT_DISALLOWED | ENT_QUOTES, 'UTF-8', FALSE ),
|
||||
'url' => (string) $conversation->url()->setQueryString( 'latest', 1 ),
|
||||
'message' => $message->truncated(),
|
||||
'date' => $message->mapped('date'),
|
||||
'author_photo' => (string) $message->author()->photo
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Log::log( "Private conversation {$conversation->id} titled {$conversation->title} has no messages", 'orphaned_data' );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Cookie Policy
|
||||
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) Invision Power Services, Inc.
|
||||
* @license https://www.invisioncommunity.com/legal/standards/
|
||||
* @package Invision Community
|
||||
* @since 12 Dec 2017
|
||||
*/
|
||||
|
||||
namespace IPS\core\modules\front\system;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cookie Policy
|
||||
*/
|
||||
class _cookies extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* Privacy Policy
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function manage()
|
||||
{
|
||||
/* Set Session Location */
|
||||
\IPS\Session::i()->setLocation( \IPS\Http\Url::internal( 'app=core&module=system&controller=cookies', NULL, 'cookies' ), array(), 'loc_viewing_cookie_policy' );
|
||||
|
||||
\IPS\Output::i()->breadcrumb[] = array( NULL, \IPS\Member::loggedIn()->language()->addToStack('cookies_about') );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('cookies_about');
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->cookies();
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,6 @@ class _designermode extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function missing()
|
||||
{
|
||||
\IPS\Output::i()->error( \IPS\Member::loggedIn()->language()->addToStack( 'theme_designers_mode_error_missing', FALSE, array( 'sprintf' => array( \IPS\Request::i()->id ) ) ), "DESMODE", 500 );
|
||||
\IPS\Output::i()->error( \IPS\Member::loggedIn()->language()->addToStack( 'theme_designers_mode_error_missing', FALSE, array( 'sprintf' => array( intval( \IPS\Request::i()->id ) ) ) ), "4C370/1", 500 );
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,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 ?: '' );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'editor', 'core', 'global' )->code( \IPS\Request::i()->val, \IPS\Request::i()->editorId, md5( mt_rand() ), \IPS\Request::i()->lang ?: '' );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,7 +155,7 @@ class _editor extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
else
|
||||
{
|
||||
$title = \IPS\Request::i()->title ?: $url;
|
||||
$title = \IPS\Request::i()->title ?: (string) $url;
|
||||
$insert = "<a href='{$url}' ipsNoEmbed='true'>{$title}</a>";
|
||||
}
|
||||
|
||||
@@ -178,41 +178,42 @@ class _editor extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Emoticons Configuration
|
||||
* Get Emoji
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function emoticons()
|
||||
protected function emoji()
|
||||
{
|
||||
$emoticons = array();
|
||||
$emoji = ( \IPS\Settings::i()->emoji_style == 'disabled' or !\IPS\Settings::i()->getFromConfGlobal('sql_utf8mb4') ) ? array() : json_decode( file_get_contents( \IPS\ROOT_PATH . '/applications/core/data/emoji.json' ), TRUE );
|
||||
|
||||
foreach ( \IPS\Db::i()->select( '*', 'core_emoticons', NULL, 'emo_set_position,emo_position' ) as $row )
|
||||
{
|
||||
if ( !isset( $emoticons[ $row['emo_set'] ] ) )
|
||||
$shortcode = ( \IPS\Settings::i()->emoji_shortcodes and preg_match( '/^:.*:$/', $row['typed'] ) );
|
||||
|
||||
try
|
||||
{
|
||||
$setLang = 'core_emoticon_group_' . $row['emo_set'];
|
||||
|
||||
$emoticons[ $row['emo_set'] ] = array(
|
||||
'title' => \IPS\Member::loggedIn()->language()->addToStack( $setLang ),
|
||||
'total' => 0,
|
||||
'emoticons' => array(),
|
||||
);
|
||||
$categoryName = \IPS\Member::loggedIn()->language()->get( 'core_emoticon_group_' . $row['emo_set'] );
|
||||
}
|
||||
catch( \UnderflowException $e )
|
||||
{
|
||||
$categoryName = '_default';
|
||||
}
|
||||
|
||||
$emoticons[ $row['emo_set'] ]['emoticons'][] = array(
|
||||
'src' => \IPS\File::get( 'core_Emoticons', $row['image'] )->url,
|
||||
'srcset' => $row['image_2x'] ? \IPS\File::get( 'core_Emoticons', $row['image_2x'] )->url . ' 2x' : FALSE,
|
||||
'height' => $row['height'] ?: FALSE,
|
||||
'width' => $row['width'] ?: FALSE,
|
||||
'text' => $row['typed']
|
||||
$emoji[ $row['emo_set'] ][] = array(
|
||||
'code' => 'custom-' . $row['emo_set'] . '-' . $row['id'],
|
||||
'name' => $row['typed'],
|
||||
'skinTone' => false,
|
||||
'shortNames' => $shortcode ? array( trim( $row['typed'], ':' ) ) : array(),
|
||||
'ascii' => $shortcode ? array() : array( $row['typed'] ),
|
||||
'categoryName' => $categoryName,
|
||||
'image' => \IPS\File::get( 'core_Emoticons', $row['image'] )->url,
|
||||
'image2x' => $row['image_2x'] ? \IPS\File::get( 'core_Emoticons', $row['image_2x'] )->url : FALSE,
|
||||
'width' => $row['width'],
|
||||
'height' => $row['height'],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( $emoticons as $set => $data )
|
||||
{
|
||||
$emoticons[ $set ]['total'] = count( $data['emoticons'] );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->json( $emoticons );
|
||||
\IPS\Output::i()->json( $emoji );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -37,9 +37,6 @@ class _followed extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Get the different types */
|
||||
$types = array();
|
||||
|
||||
/* Don't forget Members */
|
||||
$types['core'] = array( 'core_member' => "\IPS\Member" );
|
||||
|
||||
foreach ( \IPS\Content::routedClasses( TRUE, FALSE, TRUE ) as $class )
|
||||
{
|
||||
@@ -61,6 +58,9 @@ class _followed extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't forget Members - add this on to the end so it never defaults UNLESS we only have apps that do not have followable content */
|
||||
$types['core'] = array( 'core_member' => "\IPS\Member" );
|
||||
|
||||
/* What type are we looking at? */
|
||||
$currentAppModule = NULL;
|
||||
@@ -84,11 +84,6 @@ class _followed extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
foreach ( $_types as $key => $class )
|
||||
{
|
||||
if ( $key == 'core_member' )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$currentAppModule = $appModule;
|
||||
$currentType = $key;
|
||||
break 2;
|
||||
|
||||
@@ -31,11 +31,14 @@ class _guidelines extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
if ( \IPS\Settings::i()->gl_type == "none" )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '', 404 ); /* @todo Error code */
|
||||
\IPS\Output::i()->error( 'node_error', '2C380/1', 404, 'guidelines_set_to_none_admin' );
|
||||
}
|
||||
|
||||
/* Set Session Location */
|
||||
\IPS\Session::i()->setLocation( \IPS\Http\Url::internal( 'app=core&module=system&controller=guidelines', NULL, 'guidelines' ), array(), 'loc_viewing_guidelines' );
|
||||
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
|
||||
\IPS\Output::i()->breadcrumb[] = array( NULL, \IPS\Member::loggedIn()->language()->addToStack('guidelines') );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('guidelines');
|
||||
|
||||
@@ -34,24 +34,47 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('') );
|
||||
}
|
||||
|
||||
/* Force HTTPs? */
|
||||
if ( mb_strtolower( $_SERVER['REQUEST_METHOD'] ) == 'get' and \IPS\Settings::i()->logins_over_https and \IPS\Request::i()->url()->data['scheme'] !== 'https' )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=system&controller=login", 'front', 'login', NULL, \IPS\Settings::i()->logins_over_https ) );
|
||||
}
|
||||
|
||||
/* Init login class */
|
||||
$login = new \IPS\Login( \IPS\Http\Url::internal( "app=core&module=system&controller=login", 'front', 'login', NULL, \IPS\Settings::i()->logins_over_https ) );
|
||||
|
||||
/* Init login class */
|
||||
$login = new \IPS\Login( \IPS\Http\Url::internal( "app=core&module=system&controller=login", 'front', 'login' ) );
|
||||
|
||||
/* What's our referrer? */
|
||||
$ref = \IPS\Request::i()->ref;
|
||||
|
||||
/* Process */
|
||||
$error = isset( \IPS\Request::i()->_err ) && \IPS\Member::loggedIn()->language()->checkKeyExists( \IPS\Request::i()->_err ) ? \IPS\Request::i()->_err : NULL;
|
||||
$error = NULL;
|
||||
try
|
||||
{
|
||||
$member = $login->authenticate();
|
||||
if ( $member !== NULL )
|
||||
if ( $success = $login->authenticate() )
|
||||
{
|
||||
$this->_doLogin( $member, $login->flags['signin_anonymous'], $login->flags['remember_me'], \IPS\Login::getDestination(), FALSE, $login->usedHandler );
|
||||
if ( $ref and $ref = @base64_decode( $ref ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$ref = \IPS\Http\Url::createFromString( $ref );
|
||||
if ( !( $ref instanceof \IPS\Http\Url\Internal ) or $ref->base !== 'front' )
|
||||
{
|
||||
throw new \Exception;
|
||||
}
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
$ref = \IPS\Http\Url::internal('');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$ref = \IPS\Http\Url::internal('');
|
||||
}
|
||||
|
||||
if ( $success->mfa() )
|
||||
{
|
||||
$_SESSION['processing2FA'] = array( 'memberId' => $success->member->member_id, 'anonymous' => $success->anonymous, 'remember' => $success->rememberMe, 'destination' => (string) $ref, 'handler' => $success->handler->id );
|
||||
\IPS\Output::i()->redirect( $ref->setQueryString( '_mfaLogin', 1 ) );
|
||||
}
|
||||
$success->process();
|
||||
|
||||
\IPS\Output::i()->redirect( $ref->setQueryString( '_fromLogin', 1 ) );
|
||||
}
|
||||
}
|
||||
catch ( \IPS\Login\Exception $e )
|
||||
@@ -59,91 +82,33 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
if ( $e->getCode() === \IPS\Login\Exception::MERGE_SOCIAL_ACCOUNT )
|
||||
{
|
||||
$e->member = $e->member->member_id;
|
||||
$e->handler = $e->handler->id;
|
||||
$_SESSION['linkAccounts'] = json_encode( $e );
|
||||
|
||||
$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 );
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=login&do=link', 'front', 'login' )->setQueryString( 'ref', $ref ), '', 303 );
|
||||
}
|
||||
|
||||
$error = $e->getMessage();
|
||||
}
|
||||
|
||||
if ( \IPS\Request::i()->isAjax() && $error )
|
||||
{
|
||||
\IPS\Output::i()->json( array( 'status' => 'error', 'error' => $error ), 401 );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Display Login Form */
|
||||
\IPS\Output::i()->allowDefaultWidgets = FALSE;
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('login');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->login( $login->forms(), $error );
|
||||
}
|
||||
/* Display Login Form */
|
||||
\IPS\Output::i()->allowDefaultWidgets = FALSE;
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('login');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->login( $login, $ref, $error );
|
||||
|
||||
/* Set Session Location */
|
||||
\IPS\Session::i()->setLocation( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', NULL, 'login' ), array(), 'loc_logging_in' );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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\Http\Url $destination Where to redirect to
|
||||
* @param bool $bypass2FA If true, will not perform 2FA check
|
||||
* @param string $loginHandler Which login handler processed the login
|
||||
* @return void
|
||||
*/
|
||||
protected function _doLogin( $member, $anonymous=FALSE, $rememberMe=TRUE, $destination=NULL, $bypass2FA=FALSE, $loginHandler=NULL )
|
||||
{
|
||||
/* Get destination */
|
||||
if ( !$destination )
|
||||
{
|
||||
$destination = \IPS\Http\Url::internal( '' );
|
||||
}
|
||||
|
||||
/* Is this a known device? */
|
||||
$device = \IPS\Member\Device::loadOrCreate( $member );
|
||||
|
||||
/* Do we need to do 2FA? */
|
||||
if ( !$bypass2FA and $output = \IPS\MFA\MFAHandler::accessToArea( 'core', $device->known ? 'AuthenticateFrontKnown' : 'AuthenticateFront', \IPS\Http\Url::internal( '' ), $member ) )
|
||||
{
|
||||
$_SESSION['processing2FA'] = array( 'memberId' => $member->member_id, 'anonymous' => $anonymous, 'remember' => $rememberMe, 'destination' => (string) $destination, 'handler' => $loginHandler );
|
||||
\IPS\Output::i()->redirect( $destination->setQueryString( '_mfaLogin', 1 ) );
|
||||
}
|
||||
|
||||
/* Log in */
|
||||
\IPS\Session::i()->setMember( $member );
|
||||
if ( $anonymous and !\IPS\Settings::i()->disable_anonymous )
|
||||
{
|
||||
\IPS\Session::i()->setAnon();
|
||||
}
|
||||
|
||||
/* Log device */
|
||||
$device->anonymous = $anonymous and !\IPS\Settings::i()->disable_anonymous;
|
||||
$device->updateAfterAuthentication( $rememberMe, $loginHandler );
|
||||
|
||||
/* 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'] ) )
|
||||
@@ -156,7 +121,7 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/* Where do we want to go? */
|
||||
$destination = NULL;
|
||||
$destination = \IPS\Http\Url::internal( '' );
|
||||
try
|
||||
{
|
||||
$destination = \IPS\Http\Url::createFromString( $_SESSION['processing2FA']['destination'] );
|
||||
@@ -167,8 +132,9 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
$device = \IPS\Member\Device::loadOrCreate( $member );
|
||||
$output = \IPS\MFA\MFAHandler::accessToArea( 'core', $device->known ? 'AuthenticateFrontKnown' : '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, $_SESSION['processing2FA']['handler'] );
|
||||
{
|
||||
( new \IPS\Login\Success( $member, \IPS\Login\Handler::load( $_SESSION['processing2FA']['handler'] ), $_SESSION['processing2FA']['remember'], $_SESSION['processing2FA']['anonymous'] ) )->process();
|
||||
\IPS\Output::i()->redirect( $destination->setQueryString( '_fromLogin', 1 ), '', 303 );
|
||||
}
|
||||
|
||||
/* Nope, just send us where we want to go not logged in */
|
||||
@@ -199,35 +165,36 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function link()
|
||||
{
|
||||
/* Get the member we're linking with */
|
||||
if ( !isset( $_SESSION['linkAccounts'] ) )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login' ) );
|
||||
}
|
||||
$details = json_decode( $_SESSION['linkAccounts'], TRUE );
|
||||
|
||||
$member = \IPS\Member::load( $details['member'] );
|
||||
if ( !$member->member_id )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login' ) );
|
||||
}
|
||||
|
||||
$form = new \IPS\Helpers\Form( 'link_accounts', 'login' );
|
||||
if ( isset( \IPS\Request::i()->ref ) )
|
||||
/* And then handler to link with */
|
||||
$handler = \IPS\Login\Handler::load( $details['handler'] );
|
||||
|
||||
/* Init reauthentication */
|
||||
$login = new \IPS\Login( \IPS\Http\Url::internal( 'app=core&module=system&controller=login&do=link', 'front', 'login' )->setQueryString( 'ref', isset( \IPS\Request::i()->ref ) ? \IPS\Request::i()->ref : NULL ), \IPS\Login::LOGIN_REAUTHENTICATE );
|
||||
$login->reauthenticateAs = $member;
|
||||
$error = NULL;
|
||||
|
||||
/* If successful (or if there's no way to reauthenticate which would only happen if a login handler has been deleted)) complete the link... */
|
||||
try
|
||||
{
|
||||
$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() )
|
||||
{
|
||||
try
|
||||
{
|
||||
$class = 'IPS\Login\\' . ucfirst( $details['handler'] );
|
||||
$class::link( $member, $details['details'] );
|
||||
if ( $success = $login->authenticate() or ( !count( $login->usernamePasswordMethods() ) and !count( $login->buttonMethods() ) ) )
|
||||
{
|
||||
$handler->completeLink( $member, $details['details'] );
|
||||
|
||||
unset( $_SESSION['linkAccounts'] );
|
||||
|
||||
$destination = NULL;
|
||||
$destination = \IPS\Http\Url::internal( '' );
|
||||
if ( isset( \IPS\Request::i()->ref ) )
|
||||
{
|
||||
try
|
||||
@@ -240,18 +207,27 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
catch ( \Exception $e ) { }
|
||||
}
|
||||
$this->_doLogin( $member, FALSE, TRUE, $destination, FALSE, $details['handler'] );
|
||||
|
||||
$success = new \IPS\Login\Success( $member, $handler );
|
||||
if ( $success->mfa() )
|
||||
{
|
||||
$_SESSION['processing2FA'] = array( 'memberId' => $success->member->member_id, 'anonymous' => $success->anonymous, 'remember' => $success->rememberMe, 'destination' => (string) $destination, 'handler' => $success->handler->id );
|
||||
\IPS\Output::i()->redirect( $destination->setQueryString( '_mfaLogin', 1 ) );
|
||||
}
|
||||
$success->process();
|
||||
\IPS\Output::i()->redirect( $destination->setQueryString( '_fromLogin', 1 ) );
|
||||
}
|
||||
catch ( \IPS\Login\Exception $e )
|
||||
{
|
||||
$form->error = $e->getMessage();
|
||||
}
|
||||
}
|
||||
catch ( \IPS\Login\Exception $e )
|
||||
{
|
||||
$error = $e->getMessage();
|
||||
}
|
||||
|
||||
/* Otherwise show the reauthenticate form */
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('login');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->mergeSocialAccount( $details['handler'], $member, $form );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->mergeSocialAccount( $handler, $member, $login, $error );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -309,16 +285,6 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
setcookie( session_name(), '', time() - 42000, $params["path"], $params["domain"], $params["secure"], $params["httponly"] );
|
||||
session_destroy();
|
||||
|
||||
/* Login handler callback */
|
||||
foreach ( \IPS\Login::handlers( TRUE ) as $k => $handler )
|
||||
{
|
||||
try
|
||||
{
|
||||
$handler->logoutAccount( $member, $redirectUrl );
|
||||
}
|
||||
catch( \BadMethodCallException $e ) {}
|
||||
}
|
||||
|
||||
/* Member sync callback */
|
||||
$member->memberSync( 'onLogout', array( $redirectUrl ) );
|
||||
|
||||
@@ -345,7 +311,7 @@ class _login extends \IPS\Dispatcher\Controller
|
||||
/* Not logged in as admin? */
|
||||
if ( $admin->member_id != \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 )->setQueryString( array( 'ref' => base64_encode( \IPS\Request::i()->url() ), '_err' => 'login_as_user_login' ) ) );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=system&controller=login", 'front', 'login' )->setQueryString( array( 'ref' => base64_encode( \IPS\Request::i()->url() ), '_err' => 'login_as_user_login' ) ) );
|
||||
}
|
||||
|
||||
/* Do it */
|
||||
|
||||
@@ -22,6 +22,26 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
*/
|
||||
class _lostpass extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
/**
|
||||
* Execute
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
if ( \IPS\Settings::i()->allow_forgot_password == 'disabled' )
|
||||
{
|
||||
\IPS\Output::i()->error( 'page_doesnt_exist', '2S151/2', 404, '' );
|
||||
}
|
||||
|
||||
if ( \IPS\Settings::i()->allow_forgot_password == 'redirect' )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::external( \IPS\Settings::i()->allow_forgot_password_target ) );
|
||||
}
|
||||
|
||||
return parent::execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage
|
||||
*
|
||||
@@ -32,11 +52,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( 'bypassProfanity' => TRUE ), function( $val ){
|
||||
|
||||
/* Check email exists */
|
||||
$member = \IPS\Member::load( $val, 'email' );
|
||||
|
||||
if( !$member->member_id )
|
||||
if( !\IPS\Login::emailIsInUse( $val ) )
|
||||
{
|
||||
throw new \LogicException( 'lost_pass_no_email' );
|
||||
}
|
||||
@@ -47,62 +63,107 @@ class _lostpass extends \IPS\Dispatcher\Controller
|
||||
/* Handle the reset */
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
/* Load the member */
|
||||
/* If using "normal" method and we have an account, and at least one login handler we can process a password change for, we're good */
|
||||
$member = \IPS\Member::load( $values['email_address'], 'email' );
|
||||
|
||||
/* If we have an existing validation record, we can just reuse it */
|
||||
$sendEmail = TRUE;
|
||||
try
|
||||
if ( $member->member_id and \IPS\Settings::i()->allow_forgot_password == 'normal' )
|
||||
{
|
||||
$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'];
|
||||
|
||||
/* 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 ) )
|
||||
foreach ( \IPS\Login::methods() as $method )
|
||||
{
|
||||
$sendEmail = FALSE;
|
||||
if ( $method->canChangePassword( $member ) )
|
||||
{
|
||||
return $this->_sendForgotPasswordEmail( $member );
|
||||
}
|
||||
}
|
||||
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 */
|
||||
if ( $sendEmail )
|
||||
/* If not, send them to the handler if we can */
|
||||
foreach( \IPS\Login::methods() as $method )
|
||||
{
|
||||
\IPS\Email::buildFromTemplate( 'core', 'lost_password_init', array( $member, $vid ), \IPS\Email::TYPE_TRANSACTIONAL )->send( $member );
|
||||
$message = "lost_pass_confirm";
|
||||
if( $method->emailIsInUse( $values['email_address'] ) === TRUE )
|
||||
{
|
||||
if ( $url = $method->forgotPasswordUrl() )
|
||||
{
|
||||
\IPS\Output::i()->redirect( $url );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we have no way to reset the password, can we allow creating a local password as a last attempt? */
|
||||
if ( $member->member_id )
|
||||
{
|
||||
foreach( \IPS\Login::methods() as $method )
|
||||
{
|
||||
if ( $method instanceof \IPS\Login\Handler\Standard )
|
||||
{
|
||||
return $this->_sendForgotPasswordEmail( $member );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, sorry, we can't do this */
|
||||
\IPS\Output::i()->error( 'lost_pass_not_possible', '1S151/3', 403, '' );
|
||||
}
|
||||
|
||||
/* Show form */
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->lostPass( $form );
|
||||
}
|
||||
|
||||
/**
|
||||
* Send forgot password email
|
||||
*
|
||||
* @param \IPS\Member $member The member
|
||||
* @return void
|
||||
*/
|
||||
protected function _sendForgotPasswordEmail( \IPS\Member $member )
|
||||
{
|
||||
/* 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'];
|
||||
|
||||
/* 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
|
||||
{
|
||||
$message = "lost_pass_too_soon";
|
||||
\IPS\Db::i()->update( 'core_validating', array( 'email_sent' => time() ), array( 'vid=?', $vid ) );
|
||||
}
|
||||
|
||||
/* 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( $message );
|
||||
}
|
||||
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 */
|
||||
if ( $sendEmail )
|
||||
{
|
||||
\IPS\Email::buildFromTemplate( 'core', 'lost_password_init', array( $member, $vid ), \IPS\Email::TYPE_TRANSACTIONAL )->send( $member );
|
||||
$message = "lost_pass_confirm";
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->sidebar['enabled'] = FALSE;
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->lostPass( $form );
|
||||
$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( $message );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,21 +196,17 @@ class _lostpass extends \IPS\Dispatcher\Controller
|
||||
/* 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();
|
||||
|
||||
/* Now reset the member's password */
|
||||
foreach ( \IPS\Login::handlers( TRUE ) as $handler )
|
||||
/* Now reset the member's password. If no handlers accept the change, create a local password */
|
||||
if ( !$member->changePassword( $values['password'], 'lost' ) )
|
||||
{
|
||||
/* We cannot update our password in some login handlers, that's ok */
|
||||
try
|
||||
{
|
||||
$handler->changePassword( $member, $values['password'] );
|
||||
}
|
||||
catch( \BadMethodCallException $e ){}
|
||||
$member->setLocalPassword( $values['password'] );
|
||||
$member->save();
|
||||
}
|
||||
|
||||
/* Log in, and invalidate all other sessions */
|
||||
\IPS\Session::i()->setMember( $member );
|
||||
$member->invalidateSessionsAndLogins( \IPS\Session::i()->id );
|
||||
\IPS\Member\Device::loadOrCreate( $member )->updateAfterAuthentication( isset( \IPS\Request::i()->cookie['login_key'] ), '' );
|
||||
\IPS\Member\Device::loadOrCreate( $member )->updateAfterAuthentication( isset( \IPS\Request::i()->cookie['login_key'] ) );
|
||||
|
||||
/* Delete validating record and log in */
|
||||
\IPS\Db::i()->delete( 'core_validating', array( 'member_id=? AND lost_pass=1', $member->member_id ) );
|
||||
|
||||
@@ -93,6 +93,8 @@ class _metatags extends \IPS\Dispatcher\Controller
|
||||
*/
|
||||
protected function end()
|
||||
{
|
||||
\IPS\Session::i()->csrfCheck();
|
||||
|
||||
$_SESSION['live_meta_tags'] = FALSE;
|
||||
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( \IPS\Request::i()->url ) );
|
||||
|
||||
@@ -113,6 +113,12 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
/* Handle submissions */
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
/* Log if admin mail setting is changed */
|
||||
if ( \IPS\Member::loggedIn()->allow_admin_mails !== $values['allow_admin_mails'] )
|
||||
{
|
||||
\IPS\Member::loggedIn()->logHistory( 'core', 'admin_mails', array( 'enabled' => $values['allow_admin_mails'] ) );
|
||||
}
|
||||
|
||||
\IPS\Member::loggedIn()->allow_admin_mails = $values['allow_admin_mails'];
|
||||
\IPS\Member::loggedIn()->auto_track = json_encode( array(
|
||||
'content' => ( is_array( $values['auto_track'] ) AND in_array( 'content', $values['auto_track'] ) ) ? 1 : 0,
|
||||
@@ -168,12 +174,12 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
foreach ( $ext->classes as $classname )
|
||||
{
|
||||
if ( $classname == 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . ucfirst( \IPS\Request::i()->follow_area ) )
|
||||
if ( $classname == 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . mb_ucfirst( \IPS\Request::i()->follow_area ) )
|
||||
{
|
||||
$class = $classname;
|
||||
break;
|
||||
}
|
||||
if ( isset( $classname::$containerNodeClass ) and $classname::$containerNodeClass == 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . ucfirst( \IPS\Request::i()->follow_area ) )
|
||||
if ( isset( $classname::$containerNodeClass ) and $classname::$containerNodeClass == 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . mb_ucfirst( \IPS\Request::i()->follow_area ) )
|
||||
{
|
||||
$class = $classname::$containerNodeClass;
|
||||
break;
|
||||
@@ -182,7 +188,7 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
foreach( $classname::$containerFollowClasses as $followClass )
|
||||
{
|
||||
if( $followClass == 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . ucfirst( \IPS\Request::i()->follow_area ) )
|
||||
if( $followClass == 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . mb_ucfirst( \IPS\Request::i()->follow_area ) )
|
||||
{
|
||||
$class = $followClass;
|
||||
break;
|
||||
@@ -216,6 +222,11 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
$class = 'IPS\\Member';
|
||||
}
|
||||
|
||||
if( \IPS\Request::i()->follow_app == 'core' and \IPS\Request::i()->follow_area == 'club' )
|
||||
{
|
||||
$class = 'IPS\Member\Club';
|
||||
}
|
||||
|
||||
if ( !$class )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '2C154/3', 404, '' );
|
||||
@@ -223,7 +234,6 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Get thing */
|
||||
$thing = NULL;
|
||||
$indexId = NULL;
|
||||
try
|
||||
{
|
||||
if ( in_array( 'IPS\Node\Model', class_parents( $class ) ) )
|
||||
@@ -242,17 +252,19 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
catch ( \Exception $e ) { }
|
||||
}
|
||||
else if ( $class != "IPS\Member" )
|
||||
elseif ( $class == 'IPS\Member\Club' )
|
||||
{
|
||||
$thing = $class::loadAndCheckPerms( \IPS\Request::i()->follow_id );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'follow_thing', FALSE, array( 'sprintf' => array( $thing->_title ) ) );
|
||||
\IPS\Output::i()->breadcrumb = array(
|
||||
array( \IPS\Http\Url::internal( 'app=core&module=clubs&controller=directory', 'front', 'clubs_list' ), \IPS\Member::loggedIn()->language()->addToStack('module__core_clubs') ),
|
||||
array( $thing->url(), $thing->name )
|
||||
);
|
||||
}
|
||||
elseif ( $class != "IPS\Member" )
|
||||
{
|
||||
$thing = $class::loadAndCheckPerms( \IPS\Request::i()->follow_id );
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'follow_thing', FALSE, array( 'sprintf' => array( $thing->mapped('title') ) ) );
|
||||
|
||||
/* Work out the index ID */
|
||||
try
|
||||
{
|
||||
$indexId = \IPS\Content\Search\Index::i()->getIndexId( $thing );
|
||||
}
|
||||
catch ( \UnderflowException $e ) { }
|
||||
|
||||
/* Set navigation */
|
||||
$container = NULL;
|
||||
@@ -300,7 +312,7 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$type = 'follower_content';
|
||||
}
|
||||
elseif ( in_array( 'IPS\Content\Item', class_parents( $class ) ) )
|
||||
elseif ( $class == 'IPS\Member\Club' or in_array( 'IPS\Content\Item', class_parents( $class ) ) )
|
||||
{
|
||||
$type = 'new_comment';
|
||||
}
|
||||
@@ -348,8 +360,11 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
|
||||
if ( $class != "IPS\Member" )
|
||||
{
|
||||
$options['daily'] = \IPS\Member::loggedIn()->language()->addToStack('follow_type_daily');
|
||||
$options['weekly'] = \IPS\Member::loggedIn()->language()->addToStack('follow_type_weekly');
|
||||
if ( $class != "IPS\Member\Club" )
|
||||
{
|
||||
$options['daily'] = \IPS\Member::loggedIn()->language()->addToStack('follow_type_daily');
|
||||
$options['weekly'] = \IPS\Member::loggedIn()->language()->addToStack('follow_type_weekly');
|
||||
}
|
||||
$options['none'] = \IPS\Member::loggedIn()->language()->addToStack('follow_type_no_notification');
|
||||
}
|
||||
|
||||
@@ -361,7 +376,7 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
foreach ( $options as $k => $v )
|
||||
{
|
||||
$form->hiddenValues[ $k ] = $v;
|
||||
@@ -401,7 +416,6 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
'follow_notify_freq' => ( $class == "IPS\Member" ) ? 'immediate' : $values['follow_type'],
|
||||
'follow_notify_sent' => 0,
|
||||
'follow_visible' => 1,
|
||||
'follow_index_id' => $indexId,
|
||||
);
|
||||
if ( $current )
|
||||
{
|
||||
@@ -412,6 +426,33 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
\IPS\Db::i()->insert( 'core_follow', $save );
|
||||
}
|
||||
|
||||
/* Also follow all nodes if following club */
|
||||
if( $class == "IPS\Member\Club" )
|
||||
{
|
||||
foreach ( $thing->nodes() as $node )
|
||||
{
|
||||
$itemClass = $node['node_class']::$contentItemClass;
|
||||
$followApp = $itemClass::$application;
|
||||
$followArea = mb_strtolower( mb_substr( $node['node_class'], mb_strrpos( $node['node_class'], '\\' ) + 1 ) );
|
||||
|
||||
$save = array(
|
||||
'follow_id' => md5( $followApp . ';' . $followArea . ';' . $node['node_id'] . ';' . \IPS\Member::loggedIn()->member_id ),
|
||||
'follow_app' => $followApp,
|
||||
'follow_area' => $followArea,
|
||||
'follow_rel_id' => $node['node_id'],
|
||||
'follow_member_id' => \IPS\Member::loggedIn()->member_id,
|
||||
'follow_is_anon' => !$values['follow_public'],
|
||||
'follow_added' => time(),
|
||||
'follow_notify_do' => ( isset( $values['follow_type'] ) AND $values['follow_type'] == 'none' ) ? 0 : 1,
|
||||
'follow_notify_meta' => '',
|
||||
'follow_notify_freq' => $values['follow_type'],
|
||||
'follow_notify_sent' => 0,
|
||||
'follow_visible' => 1,
|
||||
);
|
||||
\IPS\Db::i()->insert( 'core_follow', $save, TRUE );
|
||||
}
|
||||
}
|
||||
|
||||
/* Send notification if following member */
|
||||
if( $class == "IPS\Member" )
|
||||
{
|
||||
@@ -463,40 +504,46 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
|
||||
\IPS\Db::i()->delete( 'core_follow', array( 'follow_id=? AND follow_member_id=?', \IPS\Request::i()->id, \IPS\Member::loggedIn()->member_id ) );
|
||||
|
||||
/* Get class */
|
||||
$class = NULL;
|
||||
foreach ( \IPS\Application::load( \IPS\Request::i()->follow_app )->extensions( 'core', 'ContentRouter' ) as $ext )
|
||||
/* Get class */
|
||||
if( \IPS\Request::i()->follow_app == 'core' and \IPS\Request::i()->follow_area == 'member' )
|
||||
{
|
||||
foreach ( $ext->classes as $classname )
|
||||
$class = 'IPS\\Member';
|
||||
}
|
||||
elseif( \IPS\Request::i()->follow_app == 'core' and \IPS\Request::i()->follow_area == 'club' )
|
||||
{
|
||||
$class = 'IPS\\Member\Club';
|
||||
}
|
||||
else
|
||||
{
|
||||
$class = NULL;
|
||||
foreach ( \IPS\Application::load( \IPS\Request::i()->follow_app )->extensions( 'core', 'ContentRouter' ) as $ext )
|
||||
{
|
||||
if ( $classname == 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . ucfirst( \IPS\Request::i()->follow_area ) )
|
||||
foreach ( $ext->classes as $classname )
|
||||
{
|
||||
$class = $classname;
|
||||
break;
|
||||
}
|
||||
if ( isset( $classname::$containerNodeClass ) and $classname::$containerNodeClass == 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . ucfirst( \IPS\Request::i()->follow_area ) )
|
||||
{
|
||||
$class = $classname::$containerNodeClass;
|
||||
break;
|
||||
}
|
||||
if( isset( $classname::$containerFollowClasses ) )
|
||||
{
|
||||
foreach( $classname::$containerFollowClasses as $followClass )
|
||||
if ( $classname == 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . mb_ucfirst( \IPS\Request::i()->follow_area ) )
|
||||
{
|
||||
if( $followClass == 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . ucfirst( \IPS\Request::i()->follow_area ) )
|
||||
$class = $classname;
|
||||
break;
|
||||
}
|
||||
if ( isset( $classname::$containerNodeClass ) and $classname::$containerNodeClass == 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . mb_ucfirst( \IPS\Request::i()->follow_area ) )
|
||||
{
|
||||
$class = $classname::$containerNodeClass;
|
||||
break;
|
||||
}
|
||||
if( isset( $classname::$containerFollowClasses ) )
|
||||
{
|
||||
foreach( $classname::$containerFollowClasses as $followClass )
|
||||
{
|
||||
$class = $followClass;
|
||||
break;
|
||||
if( $followClass == 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . mb_ucfirst( \IPS\Request::i()->follow_area ) )
|
||||
{
|
||||
$class = $followClass;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( \IPS\Request::i()->follow_app == 'core' and \IPS\Request::i()->follow_area == 'member' )
|
||||
{
|
||||
$class = 'IPS\\Member';
|
||||
}
|
||||
|
||||
/* Get thing */
|
||||
$thing = NULL;
|
||||
@@ -515,6 +562,19 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
catch ( \OutOfRangeException $e )
|
||||
{
|
||||
}
|
||||
|
||||
/* Unfollow club areas */
|
||||
if( $class == "IPS\Member\Club" )
|
||||
{
|
||||
foreach ( $thing->nodes() as $node )
|
||||
{
|
||||
$itemClass = $node['node_class']::$contentItemClass;
|
||||
$followApp = $itemClass::$application;
|
||||
$followArea = mb_strtolower( mb_substr( $node['node_class'], mb_strrpos( $node['node_class'], '\\' ) + 1 ) );
|
||||
|
||||
\IPS\Db::i()->delete( 'core_follow', array( 'follow_id=? AND follow_member_id=?', md5( $followApp . ';' . $followArea . ';' . $node['node_id'] . ';' . \IPS\Member::loggedIn()->member_id ), \IPS\Member::loggedIn()->member_id ) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
@@ -542,9 +602,13 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$class = 'IPS\\Member';
|
||||
}
|
||||
else if( \IPS\Request::i()->follow_app == 'core' and \IPS\Request::i()->follow_area == 'club' )
|
||||
{
|
||||
$class = 'IPS\\Member\Club';
|
||||
}
|
||||
else
|
||||
{
|
||||
$class = 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . ucfirst( \IPS\Request::i()->follow_area );
|
||||
$class = 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . mb_ucfirst( \IPS\Request::i()->follow_area );
|
||||
}
|
||||
|
||||
if ( !class_exists( $class ) )
|
||||
@@ -566,6 +630,13 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
$anonymous = $classname::containerFollowers( $thing, $classname::FOLLOW_ANONYMOUS )->count( TRUE );
|
||||
$title = $thing->_title;
|
||||
}
|
||||
else if ( $class == "IPS\Member\Club" )
|
||||
{
|
||||
$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->_title;
|
||||
}
|
||||
else if ( $class != "IPS\Member" )
|
||||
{
|
||||
$thing = $class::loadAndCheckPerms( \IPS\Request::i()->follow_id );
|
||||
@@ -617,9 +688,13 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$class = 'IPS\\Member';
|
||||
}
|
||||
if( \IPS\Request::i()->follow_app == 'core' and \IPS\Request::i()->follow_area == 'club' )
|
||||
{
|
||||
$class = 'IPS\\Member\Club';
|
||||
}
|
||||
else
|
||||
{
|
||||
$class = 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . ucfirst( \IPS\Request::i()->follow_area );
|
||||
$class = 'IPS\\' . \IPS\Request::i()->follow_app . '\\' . mb_ucfirst( \IPS\Request::i()->follow_area );
|
||||
}
|
||||
if ( !class_exists( $class ) )
|
||||
{
|
||||
@@ -693,6 +768,23 @@ class _notifications extends \IPS\Dispatcher\Controller
|
||||
|
||||
\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 ) );
|
||||
|
||||
if( \IPS\Request::i()->follow_area == 'club' )
|
||||
{
|
||||
try
|
||||
{
|
||||
$club = \IPS\Member\Club::load( \IPS\Request::i()->follow_id );
|
||||
foreach ( $club->nodes() as $node )
|
||||
{
|
||||
$itemClass = $node['node_class']::$contentItemClass;
|
||||
$followApp = $itemClass::$application;
|
||||
$followArea = mb_strtolower( mb_substr( $node['node_class'], mb_strrpos( $node['node_class'], '\\' ) + 1 ) );
|
||||
|
||||
\IPS\Db::i()->delete( 'core_follow', array( 'follow_app=? AND follow_area=? AND follow_rel_id=?', $followApp, $followArea, $node['node_id'] ) );
|
||||
}
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( ( !empty( $_SERVER['HTTP_REFERER'] ) ) ? \IPS\Http\Url::createFromString( $_SERVER['HTTP_REFERER'] ) : \IPS\Http\Url::internal( '' ), 'followers_removed' );
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ class _privacy extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
if ( \IPS\Settings::i()->privacy_type == "none" )
|
||||
{
|
||||
\IPS\Output::i()->error( 'node_error', '', 404 ); /* @todo Error code */
|
||||
\IPS\Output::i()->error( 'node_error', '2C381/1', 404, 'privacy_set_to_none_acp' );
|
||||
}
|
||||
|
||||
/* Set Session Location */
|
||||
|
||||
@@ -34,11 +34,19 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->redirect( \IPS\Settings::i()->base_url );
|
||||
}
|
||||
|
||||
if( !\IPS\Settings::i()->allow_reg and \IPS\Request::i()->do !== 'complete'
|
||||
if( \IPS\Request::i()->do !== 'complete'
|
||||
and \IPS\Request::i()->do !== 'changeEmail' and \IPS\Request::i()->do !== 'validate'
|
||||
and \IPS\Request::i()->do !== 'validating' and \IPS\Request::i()->do !== 'reconfirm' )
|
||||
and \IPS\Request::i()->do !== 'validating' and \IPS\Request::i()->do !== 'reconfirm'
|
||||
and \IPS\Request::i()->do !== 'finish' )
|
||||
{
|
||||
\IPS\Output::i()->error( 'reg_disabled', '2S129/5', 403, '' );
|
||||
if ( \IPS\Login::registrationType() == 'redirect' )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::external( \IPS\Settings::i()->allow_reg_target ) );
|
||||
}
|
||||
elseif ( \IPS\Login::registrationType() == 'disabled' )
|
||||
{
|
||||
\IPS\Output::i()->error( 'reg_disabled', '2S129/5', 403, '' );
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->bodyClasses[] = 'ipsLayout_minimal';
|
||||
@@ -62,20 +70,20 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
\IPS\Output::i()->allowDefaultWidgets = FALSE;
|
||||
|
||||
/* Quick registration does not work with COPPA */
|
||||
if ( \IPS\Settings::i()->quick_register )
|
||||
if ( \IPS\Login::registrationType() == 'normal' )
|
||||
{
|
||||
$form = $this->_registrationForm();
|
||||
$form->class = 'ipsForm_fullWidth';
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('registration');
|
||||
|
||||
if( (string) \IPS\Request::i()->url() == (string) \IPS\Http\Url::internal( 'app=core&module=system&controller=register', NULL, 'register' ) )
|
||||
if( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->register( $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupRegisterTemplate' ), new \IPS\Login( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login', NULL, \IPS\Settings::i()->logins_over_https ) ) ), new \IPS\Login( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login', NULL, \IPS\Settings::i()->logins_over_https ) ) );
|
||||
\IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupRegisterTemplate' ), new \IPS\Login( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login' ), \IPS\Login::LOGIN_REGISTRATION_FORM ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupRegisterTemplate' ), new \IPS\Login( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login', NULL, \IPS\Settings::i()->logins_over_https ) ) );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->register( $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core' ) ), 'popupRegisterTemplate' ), new \IPS\Login( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login' ), \IPS\Login::LOGIN_REGISTRATION_FORM ) ), new \IPS\Login( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login' ) ) );
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -137,7 +145,7 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$form = $this->_registrationForm();
|
||||
|
||||
return \IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->register( $form, new \IPS\Login( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login', NULL, \IPS\Settings::i()->logins_over_https ) ) );
|
||||
return \IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->register( $form, new \IPS\Login( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login' ), \IPS\Login::LOGIN_REGISTRATION_FORM ) );
|
||||
};
|
||||
|
||||
/* Output */
|
||||
@@ -209,18 +217,36 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* Log them in */
|
||||
\IPS\Session::i()->setMember( $member );
|
||||
\IPS\Member\Device::loadOrCreate( $member, FALSE )->updateAfterAuthentication( TRUE, '' );
|
||||
\IPS\Member\Device::loadOrCreate( $member, FALSE )->updateAfterAuthentication( TRUE, NULL );
|
||||
|
||||
$redirectUrl = \IPS\Login::getRegistrationDestination( $member );
|
||||
if ( isset( \IPS\Request::i()->ref ) and $ref = @base64_decode( \IPS\Request::i()->ref ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$ref = \IPS\Http\Url::createFromString( $ref );
|
||||
if ( !( $ref instanceof \IPS\Http\Url\Internal ) or $ref->base !== 'front' )
|
||||
{
|
||||
throw new \Exception;
|
||||
}
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
$ref = \IPS\Http\Url::internal('');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$ref = \IPS\Http\Url::internal('');
|
||||
}
|
||||
|
||||
/* Redirect */
|
||||
if ( \IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->json( array( 'redirect' => (string) $redirectUrl ) );
|
||||
\IPS\Output::i()->json( array( 'redirect' => (string) $ref ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->redirect( $redirectUrl );
|
||||
\IPS\Output::i()->redirect( $ref );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -241,7 +267,7 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
$haveRequired = FALSE;
|
||||
foreach( $steps AS $id => $step )
|
||||
{
|
||||
if ( $step->required )
|
||||
if ( $step->required AND !$step->completed( \IPS\Member::loggedIn() ) )
|
||||
{
|
||||
$haveRequired = TRUE;
|
||||
break;
|
||||
@@ -253,8 +279,7 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
/* Nope, forward */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( '' ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
$wizardSteps = array();
|
||||
$url = \IPS\Http\Url::internal( 'app=core&module=system&controller=register&do=finish', 'front', 'register' );
|
||||
foreach( \IPS\Application::allExtensions( 'core', 'ProfileSteps' ) AS $extension )
|
||||
@@ -265,6 +290,8 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
$wizardSteps = \IPS\Member\ProfileStep::setOrder( $wizardSteps );
|
||||
|
||||
$wizardSteps = array_merge( $wizardSteps, array( 'profile_done' => function( $data ) {
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( '' ), 'saved' );
|
||||
} ) );
|
||||
@@ -288,11 +315,11 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
$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, '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' ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'password', NULL, TRUE, array( 'showMeter' => \IPS\Settings::i()->password_strength_meter, 'checkStrength' => TRUE, 'bypassProfanity' => TRUE ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'password_confirm', NULL, TRUE, array( 'confirm' => 'password', 'bypassProfanity' => TRUE ) ) );
|
||||
|
||||
/* Profile fields */
|
||||
if ( ! \IPS\Settings::i()->quick_register )
|
||||
if ( \IPS\Login::registrationType() == 'full' )
|
||||
{
|
||||
foreach ( \IPS\core\ProfileFields\Field::fields( array(), \IPS\core\ProfileFields\Field::REG ) as $group => $fields )
|
||||
{
|
||||
@@ -330,7 +357,15 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
|
||||
if( $qanda )
|
||||
{
|
||||
$question = \IPS\Db::i()->select( '*', 'core_question_and_answer', array( 'qa_id=?', $qanda ) )->first();
|
||||
try
|
||||
{
|
||||
$question = \IPS\Db::i()->select( '*', 'core_question_and_answer', array( 'qa_id=?', $qanda ) )->first();
|
||||
}
|
||||
catch( \UnderflowException $e )
|
||||
{
|
||||
throw new \DomainException( 'q_and_a_incorrect' );
|
||||
}
|
||||
|
||||
$answers = json_decode( $question['qa_answers'] );
|
||||
|
||||
if( $answers )
|
||||
@@ -380,14 +415,14 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
$form->addSeparator();
|
||||
}
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Checkbox( 'reg_admin_mails', TRUE, FALSE ) );
|
||||
$form->add( new \IPS\Helpers\Form\Checkbox( 'reg_admin_mails', \IPS\Settings::i()->updates_consent_default == 'enabled' ? TRUE : FALSE, FALSE ) );
|
||||
|
||||
\IPS\Member::loggedIn()->language()->words[ "reg_agreed_terms" ] = sprintf( \IPS\Member::loggedIn()->language()->get("reg_agreed_terms"), \IPS\Http\Url::internal( 'app=core&module=system&controller=terms', 'front', 'terms' ) );
|
||||
\IPS\Member::loggedIn()->language()->words[ "reg_agreed_terms" ] = sprintf( \IPS\Member::loggedIn()->language()->get("reg_agreed_terms"), \IPS\Http\Url::internal( 'app=core&module=system&controller=terms', 'front', 'terms', array(), \IPS\Http\Url::PROTOCOL_RELATIVE ) );
|
||||
|
||||
/* Build the appropriate links for registration terms & privacy policy */
|
||||
if ( \IPS\Settings::i()->privacy_type == "internal" )
|
||||
{
|
||||
\IPS\Member::loggedIn()->language()->words[ "reg_agreed_terms" ] .= sprintf( \IPS\Member::loggedIn()->language()->get("reg_privacy_link"), \IPS\Http\Url::internal( 'app=core&module=system&controller=privacy', 'front', 'privacy' ), 'data-ipsDialog data-ipsDialog-size="wide" data-ipsDialog-title="' . \IPS\Member::loggedIn()->language()->get("privacy") . '"' );
|
||||
\IPS\Member::loggedIn()->language()->words[ "reg_agreed_terms" ] .= sprintf( \IPS\Member::loggedIn()->language()->get("reg_privacy_link"), \IPS\Http\Url::internal( 'app=core&module=system&controller=privacy', 'front', 'privacy', array(), \IPS\Http\Url::PROTOCOL_RELATIVE ), 'data-ipsDialog data-ipsDialog-size="wide" data-ipsDialog-title="' . \IPS\Member::loggedIn()->language()->get("privacy") . '"' );
|
||||
}
|
||||
else if ( \IPS\Settings::i()->privacy_type == "external" )
|
||||
{
|
||||
@@ -478,33 +513,40 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
$member = new \IPS\Member;
|
||||
$member->name = $values['username'];
|
||||
$member->email = $values['email_address'];
|
||||
$member->members_pass_salt = $member->generateSalt();
|
||||
$member->members_pass_hash = $member->encryptedPassword( $values['password'] );
|
||||
$member->setLocalPassword( $values['password'] );
|
||||
$member->allow_admin_mails = $values['reg_admin_mails'];
|
||||
$member->member_group_id = \IPS\Settings::i()->member_group;
|
||||
$member->members_bitoptions['view_sigs'] = TRUE;
|
||||
$member->last_visit = time();
|
||||
|
||||
/* Query spam service */
|
||||
$spamCode = NULL;
|
||||
$spamAction = NULL;
|
||||
if( \IPS\Settings::i()->spam_service_enabled )
|
||||
{
|
||||
if( $member->spamService() == 4 )
|
||||
$spamAction = $member->spamService( 'register', NULL, $spamCode );
|
||||
if( $spamAction == 4 )
|
||||
{
|
||||
\IPS\Output::i()->error( 'spam_denied_account', '2S129/1', 403, '' );
|
||||
}
|
||||
}
|
||||
|
||||
/* Initial Save */
|
||||
$member->save();
|
||||
|
||||
/* This looks a bit weird, but the extensions expect an account to exist at this point, so we'll let the system save it now, then do what we need to do, then save again */
|
||||
foreach( \IPS\Member\ProfileStep::loadAll() AS $step )
|
||||
if ( \IPS\Settings::i()->quick_register )
|
||||
{
|
||||
$extension = $step->extension;
|
||||
$extension::formatFormValues( $values, $member, $form );
|
||||
/* Initial Save */
|
||||
$member->save();
|
||||
|
||||
/* This looks a bit weird, but the extensions expect an account to exist at this point, so we'll let the system save it now, then do what we need to do, then save again */
|
||||
foreach( \IPS\Member\ProfileStep::loadAll() AS $step )
|
||||
{
|
||||
$extension = $step->extension;
|
||||
$extension::formatFormValues( $values, $member, $form );
|
||||
}
|
||||
}
|
||||
|
||||
/* Save anything the profile extensions did */
|
||||
$member->save();
|
||||
$member->logHistory( 'core', 'account', array( 'type' => 'register', 'spamCode' => $spamCode, 'spamAction' => $spamAction ), FALSE );
|
||||
|
||||
/* Security Questions */
|
||||
if ( \IPS\Settings::i()->security_questions_enabled and in_array( \IPS\Settings::i()->security_questions_prompt, array( 'register', 'optional' ) ) )
|
||||
@@ -550,7 +592,18 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
\IPS\Db::i()->replace( 'core_pfields_content', array_merge( array( 'member_id' => $member->member_id ), $profileFields ) );
|
||||
}
|
||||
|
||||
|
||||
/* Log that we gave consent for admin emails */
|
||||
$member->logHistory( 'core', 'admin_mails', array( 'enabled' => (boolean) $member->allow_admin_mails ) );
|
||||
|
||||
/* Log that we gave consent for terms and privacy */
|
||||
if ( \IPS\Settings::i()->privacy_type != 'none' )
|
||||
{
|
||||
$member->logHistory( 'core', 'terms_acceptance', array( 'type' => 'privacy' ) );
|
||||
}
|
||||
|
||||
$member->logHistory( 'core', 'terms_acceptance', array( 'type' => 'terms' ) );
|
||||
|
||||
/* Handle validation */
|
||||
$member->postRegistration();
|
||||
|
||||
@@ -593,7 +646,13 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/* They're not validated but in what way? */
|
||||
if( $validating['user_verified'] )
|
||||
if ( $validating['reg_cancelled'] )
|
||||
{
|
||||
/* They are cancelled and will be deleted, haha, etc */
|
||||
\IPS\Output::i()->error( 'reg_is_cancelled', '2C223/9', 403, '' );
|
||||
|
||||
}
|
||||
else if ( $validating['user_verified'] )
|
||||
{
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->notAdminValidated();
|
||||
}
|
||||
@@ -690,7 +749,7 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
/* 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 ) );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=login', 'front', 'login' ) );
|
||||
}
|
||||
elseif ( \IPS\Member::loggedIn()->real_name and \IPS\Member::loggedIn()->email )
|
||||
{
|
||||
@@ -711,6 +770,17 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
$form->add( new \IPS\Helpers\Form\Email( 'email_address', NULL, TRUE, array( 'accountEmail' => TRUE ) ) );
|
||||
}
|
||||
if ( \IPS\Member::loggedIn()->members_bitoptions['must_reaccept_terms'] )
|
||||
{
|
||||
\IPS\Member::loggedIn()->language()->words[ "reg_agreed_terms" ] = sprintf( \IPS\Member::loggedIn()->language()->get("reg_agreed_terms"), \IPS\Http\Url::internal( 'app=core&module=system&controller=terms', 'front', 'terms' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Checkbox( 'reg_agreed_terms', NULL, TRUE, array(), function( $val )
|
||||
{
|
||||
if ( !$val )
|
||||
{
|
||||
throw new \InvalidArgumentException('reg_not_agreed_terms');
|
||||
}
|
||||
} ) );
|
||||
}
|
||||
$form->addButton( 'cancel', 'link', \IPS\Http\Url::internal( 'app=core&module=system&controller=register&do=cancel', 'front', 'register' )->csrf() );
|
||||
|
||||
/* Handle the submission */
|
||||
@@ -720,13 +790,16 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
\IPS\Member::loggedIn()->name = $values['username'];
|
||||
}
|
||||
$spamCode = NULL;
|
||||
$spamAction = NULL;
|
||||
if( isset( $values['email_address'] ) )
|
||||
{
|
||||
\IPS\Member::loggedIn()->email = $values['email_address'];
|
||||
|
||||
if( \IPS\Settings::i()->spam_service_enabled )
|
||||
{
|
||||
if( \IPS\Member::loggedIn()->spamService() == 4 )
|
||||
$spamAction = \IPS\Member::loggedIn()->spamService( 'register', NULL, $spamCode );
|
||||
if( $spamAction == 4 )
|
||||
{
|
||||
$action = \IPS\Settings::i()->spam_service_action_4;
|
||||
|
||||
@@ -740,9 +813,11 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Member::loggedIn()->members_bitoptions['must_reaccept_terms'] = FALSE;
|
||||
|
||||
/* Save */
|
||||
\IPS\Member::loggedIn()->save();
|
||||
\IPS\Member::loggedIn()->logHistory( 'core', 'account', array( 'type' => 'complete' ), FALSE );
|
||||
|
||||
/* Handle validation */
|
||||
\IPS\Member::loggedIn()->postRegistration( ( isset( $values['email_address'] ) ) ? FALSE : TRUE );
|
||||
@@ -751,7 +826,26 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
\IPS\Session::i()->setType( \IPS\Session\Front::LOGIN_TYPE_MEMBER );
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( \IPS\Login::getRegistrationDestination( \IPS\Member::loggedIn() ) );
|
||||
if ( isset( \IPS\Request::i()->ref ) and $ref = @base64_decode( \IPS\Request::i()->ref ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$ref = \IPS\Http\Url::createFromString( $ref );
|
||||
if ( !( $ref instanceof \IPS\Http\Url\Internal ) or $ref->base !== 'front' )
|
||||
{
|
||||
throw new \Exception;
|
||||
}
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
$ref = \IPS\Http\Url::internal('');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$ref = \IPS\Http\Url::internal('');
|
||||
}
|
||||
\IPS\Output::i()->redirect( $ref );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('reg_complete_details');
|
||||
@@ -784,7 +878,7 @@ 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 ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Email( 'new_email', '', TRUE, array( 'accountEmail' => \IPS\Member::loggedIn() ) ) );
|
||||
$captcha = new \IPS\Helpers\Form\Captcha;
|
||||
if ( (string) $captcha !== '' )
|
||||
{
|
||||
@@ -794,17 +888,33 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
/* Handle submissions */
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
/* Check spam defense whitelist */
|
||||
if( \IPS\Settings::i()->spam_service_enabled AND ( isset( $pending['new_reg'] ) AND $pending['new_reg'] ) AND \IPS\Member::loggedIn()->spamDefenseWhitelist() )
|
||||
{
|
||||
/* We specifically say it's 'register' so that actions are still performed on the account */
|
||||
$newEmailScore = \IPS\Member::loggedIn()->spamService( 'register', $values['new_email'] );
|
||||
|
||||
/* Is it a ban response? */
|
||||
if( $newEmailScore == 4 )
|
||||
{
|
||||
\IPS\Output::i()->error( 'spam_denied_account', '2C223/A', 403, '' );
|
||||
}
|
||||
}
|
||||
|
||||
/* Change the email */
|
||||
$oldEmail = \IPS\Member::loggedIn()->email;
|
||||
foreach ( \IPS\Login::handlers( TRUE ) as $handler )
|
||||
\IPS\Member::loggedIn()->email = $values['new_email'];
|
||||
\IPS\Member::loggedIn()->save();
|
||||
foreach ( \IPS\Login::methods() as $method )
|
||||
{
|
||||
try
|
||||
{
|
||||
$handler->changeEmail( \IPS\Member::loggedIn(), $oldEmail, $values['new_email'] );
|
||||
$method->changeEmail( \IPS\Member::loggedIn(), $oldEmail, $values['new_email'] );
|
||||
}
|
||||
catch( \BadMethodCallException $e ) {}
|
||||
}
|
||||
\IPS\Member::loggedIn()->save();
|
||||
\IPS\Member::loggedIn()->memberSync( 'onEmailChange', array( $values['new_email'], $oldEmail ) );
|
||||
\IPS\Member::loggedIn()->logHistory( 'core', 'email_change', array( 'old' => $oldEmail, 'new' => $values['new_email'], 'by' => 'manual' ) );
|
||||
|
||||
/* Invalidate sessions except this one */
|
||||
\IPS\Member::loggedIn()->invalidateSessionsAndLogins( \IPS\Session::i()->id );
|
||||
@@ -879,16 +989,9 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
|
||||
/* 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 ) {}
|
||||
}
|
||||
|
||||
/* Flag user as having cancelled their registration */
|
||||
\IPS\Db::i()->update( 'core_validating', array( 'reg_cancelled' => time() ), array( 'member_id=? AND new_reg=1', \IPS\Member::loggedIn()->member_id ) );
|
||||
|
||||
/* Redirect */
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( '' ), 'reg_canceled' );
|
||||
@@ -902,23 +1005,27 @@ class _register extends \IPS\Dispatcher\Controller
|
||||
protected function reconfirm()
|
||||
{
|
||||
/* Generate form */
|
||||
$form = new \IPS\Helpers\Form;
|
||||
$form = new \IPS\Helpers\Form( 'reconfirm_checkbox', 'reconfirm_checkbox' );
|
||||
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 )
|
||||
{
|
||||
if ( !$val )
|
||||
{
|
||||
throw new \InvalidArgumentException('reg_not_agreed_terms');
|
||||
}
|
||||
} ) );
|
||||
|
||||
/* Handle submissions */
|
||||
if ( $values = $form->values() )
|
||||
{
|
||||
/* Log that we gave consent */
|
||||
if ( \IPS\Member::loggedIn()->members_bitoptions['must_reaccept_privacy'] )
|
||||
{
|
||||
\IPS\Member::loggedIn()->logHistory( 'core', 'terms_acceptance', array( 'type' => 'privacy' ) );
|
||||
}
|
||||
|
||||
if ( \IPS\Member::loggedIn()->members_bitoptions['must_reaccept_terms'] )
|
||||
{
|
||||
\IPS\Member::loggedIn()->logHistory( 'core', 'terms_acceptance', array( 'type' => 'terms' ) );
|
||||
}
|
||||
|
||||
\IPS\Member::loggedIn()->members_bitoptions['must_reaccept_privacy'] = FALSE;
|
||||
\IPS\Member::loggedIn()->members_bitoptions['must_reaccept_terms'] = FALSE;
|
||||
\IPS\Member::loggedIn()->save();
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -31,10 +31,10 @@ class _twitter extends \IPS\Dispatcher\Controller
|
||||
{
|
||||
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 )->setQueryString( 'ref', base64_encode( \IPS\Http\Url::internal( 'app=core&module=system&controller=twitter' ) ) ) );
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=system&controller=login", 'front', 'login' )->setQueryString( 'ref', base64_encode( \IPS\Http\Url::internal( 'app=core&module=system&controller=twitter' ) ) ) );
|
||||
}
|
||||
|
||||
$twitter = \IPS\Login::getHandler('Twitter');
|
||||
$twitter = \IPS\Login\Handler::findMethod('IPS\Login\Handler\Oauth1\Twitter');
|
||||
$promote = \IPS\core\Promote::getPromoter( 'Twitter' );
|
||||
$url = \IPS\Http\Url::internal( 'app=core&module=system&controller=twitter' );
|
||||
|
||||
@@ -43,8 +43,7 @@ class _twitter extends \IPS\Dispatcher\Controller
|
||||
/* Get a request token */
|
||||
if ( !isset( \IPS\Request::i()->oauth_token ) )
|
||||
{
|
||||
$callback = $url->setQueryString( 'csrf', \IPS\Session::i()->csrfKey );
|
||||
$response = $twitter->sendRequest( 'get', 'https://api.twitter.com/oauth/request_token', array( 'oauth_callback' => (string) $callback ) )->decodeQueryString('oauth_token');
|
||||
$response = $twitter->requestToken( $url->setQueryString( 'csrf', \IPS\Session::i()->csrfKey ) );
|
||||
\IPS\Output::i()->redirect( "https://api.twitter.com/oauth/authorize?force_login=1&oauth_token={$response['oauth_token']}" );
|
||||
}
|
||||
|
||||
@@ -55,9 +54,7 @@ class _twitter extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
|
||||
/* Authenticate */
|
||||
$response = $twitter->sendRequest( 'post', 'https://api.twitter.com/oauth/access_token', array( 'oauth_verifier' => \IPS\Request::i()->oauth_verifier ), \IPS\Request::i()->oauth_token )->decodeQueryString('user_id');
|
||||
|
||||
$user = $twitter->sendRequest( 'get', 'https://api.twitter.com/1.1/account/verify_credentials.json', array(), $response['oauth_token'], $response['oauth_token_secret'] )->decodeJson();
|
||||
$response = $twitter->exchangeToken( \IPS\Request::i()->oauth_verifier, \IPS\Request::i()->oauth_token );
|
||||
|
||||
/* Store the settings */
|
||||
$promote->saveSettings( array(
|
||||
@@ -65,17 +62,19 @@ class _twitter extends \IPS\Dispatcher\Controller
|
||||
'owner' => \IPS\Member::loggedIn()->member_id,
|
||||
'secret' => $response['oauth_token_secret'],
|
||||
'token' => $response['oauth_token'],
|
||||
'name' => $user['screen_name']
|
||||
'name' => $response['screen_name']
|
||||
) );
|
||||
|
||||
/* Show a done page */
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('promote_twitter_sorted');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'promote' )->promoteTwitterComplete( $user );
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'promote' )->promoteTwitterComplete( $response );
|
||||
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
throw new \IPS\Login\Exception( 'generic_error', \IPS\Login\Exception::INTERNAL_ERROR );
|
||||
\IPS\Log::log( $e, 'twitter_promote' );
|
||||
|
||||
\IPS\Output::i()->error( 'generic_error', '4C375/1', 403, $e->getMessage() );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,9 @@ class _unsubscribe extends \IPS\Dispatcher\Controller
|
||||
$member->allow_admin_mails = 0;
|
||||
$member->save();
|
||||
|
||||
/* Log it */
|
||||
$member->logHistory( 'core', 'admin_mails', array( 'enabled' => FALSE ) );
|
||||
|
||||
/* And then show them a confirmation screen */
|
||||
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('unsubscribed');
|
||||
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'system' )->unsubscribed();
|
||||
|
||||
@@ -81,7 +81,7 @@ class _vse extends \IPS\Dispatcher\Controller
|
||||
/* VSE CSS */
|
||||
if ( isset( $css['core']['front']['custom']['vse.css'] ) )
|
||||
{
|
||||
$functionName = "css_" . uniqid();
|
||||
$functionName = "css_" . mt_rand();
|
||||
\IPS\Theme::makeProcessFunction( \IPS\Theme::fixResourceTags( $css['core']['front']['custom']['vse.css']['css_content'], 'front' ), $functionName, '', FALSE, TRUE );
|
||||
$vseCss = call_user_func( 'IPS\\Theme\\'. $functionName );
|
||||
}
|
||||
@@ -89,7 +89,7 @@ class _vse extends \IPS\Dispatcher\Controller
|
||||
if ( isset( $css['core']['front']['custom']['custom.css'] ) )
|
||||
{
|
||||
/* Custom CSS */
|
||||
$functionName = "css_" . uniqid();
|
||||
$functionName = "css_" . mt_rand();
|
||||
\IPS\Theme::makeProcessFunction( \IPS\Theme::fixResourceTags( $css['core']['front']['custom']['custom.css']['css_content'], 'front' ), $functionName, '', FALSE, TRUE );
|
||||
$customCss = call_user_func( 'IPS\\Theme\\'. $functionName );
|
||||
}
|
||||
@@ -133,10 +133,16 @@ class _vse extends \IPS\Dispatcher\Controller
|
||||
$options['options'] = $options;
|
||||
break;
|
||||
}
|
||||
|
||||
$field = new $class( "core_theme_setting_title_{$data['sc_id']}", $value, false, $options );
|
||||
$field->label = \IPS\Member::loggedIn()->language()->addToStack( $data['sc_title'], FALSE, array( 'escape' => true ) );
|
||||
$form->add( $field );
|
||||
if ( class_exists( $class ) )
|
||||
{
|
||||
$field = new $class( "core_theme_setting_title_{$data['sc_id']}", $value, false, $options );
|
||||
$field->label = \IPS\Member::loggedIn()->language()->addToStack( $data['sc_title'], FALSE, array( 'escape' => true ) );
|
||||
$form->add( $field );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Log::log( 'VSE tried to load ' . $class . ' for theme setting ' . $key, 'vse_error' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ class _warnings extends \IPS\Content\Controller
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C184/6', 403, '' );
|
||||
}
|
||||
|
||||
|
||||
/* Build the form */
|
||||
$form = \IPS\core\Warnings\Warning::create();
|
||||
$form->class = 'ipsForm_vertical';
|
||||
@@ -165,7 +165,7 @@ class _warnings extends \IPS\Content\Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Axknowledge Warning
|
||||
* Acknowledge Warning
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
@@ -262,7 +262,13 @@ class _warnings extends \IPS\Content\Controller
|
||||
* @return void
|
||||
*/
|
||||
protected function reasonAjax()
|
||||
{
|
||||
{
|
||||
/* Check permission */
|
||||
if ( ! ( \IPS\Settings::i()->warn_on AND \IPS\Member::loggedIn()->modPermission('mod_see_warn') ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C135/9', 403, '' );
|
||||
}
|
||||
|
||||
$remove = array(
|
||||
'date' => NULL,
|
||||
'time' => NULL,
|
||||
@@ -351,6 +357,13 @@ class _warnings extends \IPS\Content\Controller
|
||||
);
|
||||
|
||||
$member = \IPS\Member::load( \IPS\Request::i()->member );
|
||||
|
||||
/* Check permission */
|
||||
if ( !( \IPS\Settings::i()->warn_on AND ( \IPS\Member::loggedIn()->modPermission('mod_see_warn') or ( \IPS\Settings::i()->warn_show_own and \IPS\Member::loggedIn()->member_id == $member->member_id ) ) ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2C135/9', 403, '' );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$action = \IPS\Db::i()->select( '*', 'core_members_warn_actions', array( 'wa_points<=?', ( $member->warn_level + \IPS\Request::i()->points ) ), 'wa_points DESC', 1 )->first();
|
||||
|
||||
@@ -68,7 +68,7 @@ class _widgets extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
|
||||
$block = \IPS\Widget::load( $appOrPlugin, $widget['key'], uniqid(), array(), $widget['restrict'], null );
|
||||
$block = \IPS\Widget::load( $appOrPlugin, $widget['key'], mt_rand(), array(), $widget['restrict'], null );
|
||||
$block->allowReuse = (boolean) $widget['allow_reuse'];
|
||||
$block->menuStyle = $widget['menu_style'];
|
||||
|
||||
@@ -131,12 +131,20 @@ class _widgets extends \IPS\Dispatcher\Controller
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( \OutOfRangeException $e ) { }
|
||||
catch ( \UnderflowException $e ) { }
|
||||
}
|
||||
|
||||
if ( !isset( $widget ) )
|
||||
{
|
||||
$widget = \IPS\Widget::load( ( $key[0] == 'plugin' ) ? \IPS\Plugin::load( $key[1] ) : \IPS\Application::load( $key[1] ), $key[2], $key[3], array(), null, \IPS\Request::i()->orientation );
|
||||
try
|
||||
{
|
||||
$widget = \IPS\Widget::load( ( $key[0] == 'plugin' ) ? \IPS\Plugin::load( $key[1] ) : \IPS\Application::load( $key[1] ), $key[2], $key[3], array(), null, \IPS\Request::i()->orientation );
|
||||
}
|
||||
catch( \OutOfRangeException $e )
|
||||
{
|
||||
$widget = '';
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->sendOutput( (string) $widget );
|
||||
@@ -217,6 +225,7 @@ class _widgets extends \IPS\Dispatcher\Controller
|
||||
|
||||
$blocks[ $k ]['configuration'] = $values;
|
||||
\IPS\Db::i()->insert( 'core_widget_areas', array( 'app' => \IPS\Request::i()->pageApp, 'module' => \IPS\Request::i()->pageModule, 'controller' => \IPS\Request::i()->pageController, 'area' => \IPS\Request::i()->pageArea, 'widgets' => json_encode( $blocks ) ), TRUE );
|
||||
\IPS\Widget::deleteCaches( $block['key'], ( isset( $block['app'] ) ) ? $block['app'] : NULL, ( isset( $block['plugin'] ) ) ? $block['plugin'] : NULL );
|
||||
\IPS\Output::i()->json( 'OK' );
|
||||
}
|
||||
\IPS\Output::i()->output = $widget->configuration()->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'widgets', 'core' ) ), 'formTemplate' ), $widget );
|
||||
|
||||
@@ -30,7 +30,7 @@ class _admin extends \IPS\Dispatcher\Controller
|
||||
$form = new \IPS\Helpers\Form( 'admin', 'continue' );
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'admin_user', NULL, TRUE ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'admin_pass1', NULL, TRUE ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'admin_pass1', NULL, TRUE, array() ) );
|
||||
$form->add( new \IPS\Helpers\Form\Password( 'admin_pass2', NULL, TRUE, array( 'confirm' => 'admin_pass1' ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Email( 'admin_email', NULL, TRUE ) );
|
||||
|
||||
|
||||
@@ -119,6 +119,9 @@ class _applications extends \IPS\Dispatcher\Controller
|
||||
'getHtml' => function( $element ) use ( $apps )
|
||||
{
|
||||
$options = array_combine( array_keys( $apps ), array_map( function( $value ){ return $value['name']; }, $apps ) );
|
||||
/* But put system app at end of list to ensure it's not selected by default over something else */
|
||||
unset( $options['core'] );
|
||||
$options['core'] = $apps['core']['name'];
|
||||
return \IPS\Theme::i()->getTemplate( 'forms' )->select( 'default_app', $element->value, TRUE, $options );
|
||||
},
|
||||
'validate' => function( $element ) use ( $apps )
|
||||
|
||||
@@ -42,11 +42,7 @@ class _done extends \IPS\Dispatcher\Controller
|
||||
|
||||
require \IPS\ROOT_PATH . '/conf_global.php';
|
||||
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => $INFO['lkey'] ), array( 'conf_key=?', 'ipb_reg_number' ) );
|
||||
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => md5( $INFO['sql_pass'] . $INFO['base_url'] . $INFO['sql_database'] ) ), array( 'conf_key=?', 'site_secret_key' ) );
|
||||
\IPS\Settings::i()->ipb_reg_number = $INFO['lkey'];
|
||||
\IPS\Settings::i()->site_secret_key = md5( $INFO['sql_pass'] . $INFO['base_url'] . $INFO['sql_database'] );
|
||||
unset( \IPS\Data\Store::i()->settings );
|
||||
\IPS\Settings::i()->changeValues( array( 'ipb_reg_number' => $INFO['lkey'], 'site_secret_key' => md5( $INFO['sql_pass'] . $INFO['base_url'] . $INFO['sql_database'] ) ) );
|
||||
|
||||
\file_put_contents( \IPS\ROOT_PATH . '/conf_global.php', "<?php\n\n" . '$INFO = ' . var_export( array(
|
||||
'sql_host' => $INFO['sql_host'],
|
||||
|
||||
@@ -30,7 +30,7 @@ class _license extends \IPS\Dispatcher\Controller
|
||||
public function manage()
|
||||
{
|
||||
$form = new \IPS\Helpers\Form( 'license', 'continue', \IPS\Http\Url::external( ( \IPS\Request::i()->isSecure() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'] . '?controller=license' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'lkey', 'Nulled by IPBMafia.ru | 25.07.2017', TRUE, array( 'size' => 50 ), function( $val )
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'lkey', 'Nulled by IPBMafia.ru | 18.04.2018', TRUE, array( 'size' => 50 ), function( $val )
|
||||
{
|
||||
\IPS\IPS::checkLicenseKey( $val, ( \IPS\Request::i()->isSecure() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . mb_substr( $_SERVER['SCRIPT_NAME'], 0, -mb_strlen( \IPS\CP_DIRECTORY . '/install/index.php' ) ) );
|
||||
}, NULL, '<a href="' . \IPS\Http\Url::ips( 'docs/find_lkey' ) . '" target="_blank">' . \IPS\Member::loggedIn()->language()->addToStack('lkey_help') . '</a>' ) );
|
||||
|
||||
@@ -57,8 +57,16 @@ class _done extends \IPS\Dispatcher\Controller
|
||||
unset( $_SESSION['sqlFinished'] );
|
||||
}
|
||||
|
||||
if( isset( $_SESSION['uniqueKey'] ) )
|
||||
{
|
||||
unset( $_SESSION['uniqueKey'] );
|
||||
}
|
||||
|
||||
unset( $_SESSION['key'] );
|
||||
|
||||
/* Unset settings datastore to prevent any upgrade settings that were overridden becoming persistent */
|
||||
\IPS\Settings::i()->clearCache();
|
||||
|
||||
/* IPS Cloud Sync */
|
||||
\IPS\IPS::resyncIPSCloud('Upgraded community');
|
||||
|
||||
|
||||
Loaded 100 of 1349 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user