<?php
/**
* @brief Support Wizard
* @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 21 May 2014
*/
namespace IPS\core\modules\admin\support;
/* 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;
}
/**
* Support Wizard
*/
class _support extends \IPS\Dispatcher\Controller
{
/**
* Execute
*
* @return void
*/
public function execute()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'get_support' );
parent::execute();
}
/**
* Support Wizard
*
* @return void
*/
protected function manage()
{
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('get_support');
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js('admin_support.js', 'core', 'admin') );
\IPS\Output::i()->output = \IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'support' )->support( new \IPS\Helpers\Wizard( array( 'type_of_problem' => array( $this, '_typeOfProblem' ), 'self_service' => array( $this, '_selfService' ), 'contact_support' => array( $this, '_contactSupport' ) ), \IPS\Http\Url::internal('app=core&module=support&controller=support') ), \IPS\Db::i()->select( 'COUNT(*)', 'core_hooks' )->first() );
\IPS\Output::i()->sidebar['actions']['systemcheck'] = array(
'icon' => 'search',
'link' => \IPS\Http\Url::internal( 'app=core&module=support&controller=support&do=systemCheck' ),
'title' => 'requirements_checker',
);
}
/**
* phpinfo
*
* @return void
*/
protected function phpinfo()
{
phpinfo();
exit;
}
/**
* System Check
*
* @return void
*/
protected function systemCheck()
{
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('requirements_checker');
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'support' )->healthcheck( \IPS\core\Setup\Upgrade::systemRequirements() );
}
/**
* Step 1: Type of problem
*
* @param mixed $data Wizard data
* @return string|array
*/
public function _typeOfProblem( $data )
{
$form = new \IPS\Helpers\Form( 'form', 'continue' );
$form->class = 'ipsForm_horizontal';
$form->add( new \IPS\Helpers\Form\Radio( 'type_of_problem_select', NULL, TRUE, array(
'options' => array( 'advice' => 'type_of_problem_advice', 'issue' => 'type_of_problem_issue' ),
'toggles' => array( 'advice' => array( 'support_advice_search' ) )
) ) );
$form->add( new \IPS\Helpers\Form\Text( 'support_advice_search', NULL, NULL, array(), function( $val )
{
if ( !$val and \IPS\Request::i()->type_of_problem_select === 'advice' )
{
throw new \DomainException('form_required');
}
}, NULL, NULL, 'support_advice_search' ) );
if ( $values = $form->values() )
{
return array( 'type' => $values['type_of_problem_select'], 'keyword' => $values['support_advice_search'] );
}
return (string) $form;
}
/**
* Step 2: Self Service
*
* @param mixed $data Wizard data
* @return string|array
*/
public function _selfService( $data )
{
if ( isset( \IPS\Request::i()->next ) )
{
return $data;
}
/* Advice */
if ( $data['type'] === 'advice' )
{
$searchResults = array();
if ( $data['keyword'] )
{
$search = new \IPS\core\extensions\core\LiveSearch\Settings;
$searchResults = $search->getResults( $data['keyword'] );
}
$guides = array();
try
{
$guides = \IPS\Http\Url::ips( 'guides/' . urlencode( $data['keyword'] ) )->request()->get()->decodeJson();
}
catch ( \Exception $e ) { }
if ( count( $searchResults ) or count( $guides ) )
{
return \IPS\Theme::i()->getTemplate( 'support' )->advice( $searchResults, $guides );
}
else
{
return $data;
}
}
/* Issue */
else
{
/* Get requirements and suggestions */
$requirementsCheck = \IPS\core\Setup\Upgrade::systemRequirements();
$this->_clearCaches();
return \IPS\Theme::i()->getTemplate( 'support' )->diagnostics(
(bool) $this->_requirementsChecker( $requirementsCheck ),
$this->_upgradeCheck(),
(bool) $this->_md5sumChecker(),
(bool) $this->_databaseChecker(),
$this->_connectionChecker(),
$this->_thirdPartyCustomizations(),
$this->_adviceChecker( $requirementsCheck ),
$requirementsCheck
);
}
}
/**
* Step 2: Self Service - Clear Caches
*
* @return NULL
*/
protected function _clearCaches()
{
/* Clear JS Maps first */
\IPS\Output::clearJsFiles();
/* 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();
}
\IPS\Data\Store::i()->clearAll();
\IPS\Data\Cache::i()->clearAll();
\IPS\Member::clearCreateMenu();
}
/**
* Step 2: Self Service - Database Checker
*
* @return array Changes necessary
*/
protected function _databaseChecker()
{
$changesToMake = array();
foreach ( \IPS\Application::applications() as $app )
{
$changesToMake = array_merge( $changesToMake, $app->databaseCheck() );
}
return $changesToMake;
}
/**
* Step 2: Self Service - Check for Uprade / known issues
*
* @return bool|array
*/
protected function _upgradeCheck()
{
return NULL;
}
/**
* Step 2: "Help me fix this" for database check fail
*
* @return void
*/
protected function databasefail()
{
$changesToMake = $this->_databaseChecker();
\IPS\Output::i()->httpHeaders['X-IPS-FormNoSubmit'] = "true";
if ( isset( \IPS\Request::i()->run ) )
{
$erroredQueries = array();
$errors = array();
foreach ( $changesToMake as $query )
{
try
{
\IPS\Db::i()->query( $query['query'] );
}
catch ( \Exception $e )
{
$erroredQueries[] = $query['query'];
$errors[] = $e->getMessage();
}
}
if ( count( $erroredQueries ) )
{
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'support' )->fixDatabase( $erroredQueries, $errors );
}
else
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=core&module=support&controller=support') );
}
}
else
{
$queries = array();
foreach ( $changesToMake as $query )
{
$queries[] = $query['query'];
}
if ( count( $queries ) )
{
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'support' )->fixDatabase( $queries, NULL );
}
else
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=core&module=support&controller=support') );
}
}
}
/**
* Step 2: Self Service - md5sum Checker
*
* @return array Modified files
*/
protected function _md5sumChecker()
{
return NULL;
}
/**
* Step 2: "Help me fix this" for md5sum fail
*
* @return void
*/
protected function md5fail()
{
return NULL;
}
/**
* Step 2: Self Service - Requirements Checker (Includes File Permissions)
*
* @param array $requirements Requirements to check
* @return array Necessary changes
*/
protected function _requirementsChecker( $check )
{
$return = array();
foreach ( $check['requirements'] as $group => $requirements )
{
foreach ( $requirements as $requirement )
{
if ( !$requirement['success'] )
{
$return[] = $requirement['message'];
}
}
}
return $return;
}
/**
* Step 2: Self Service - Check advice and look for recommendations
*
* @param array $check Requirements to check
* @return array Necessary changes
*/
protected function _adviceChecker( $check )
{
$return = array();
if( isset( $check['advice'] ) )
{
foreach ( $check['advice'] as $suggestion )
{
$return[] = $suggestion;
}
}
if( \IPS\Settings::i()->getFromConfGlobal('sql_utf8mb4') !== TRUE )
{
$return[] = \IPS\Member::loggedIn()->language()->addToStack('utf8mb4_generic_explain');
}
return $return;
}
/**
* Step 2: Self Service - Connection and server clock checker
*
* @return int or string with error
*/
protected function _connectionChecker()
{
return 1;
}
/**
* Step 2: "Help me fix this" for connection check fail
*
* @return void
*/
protected function connectionfail()
{
return NULL;
}
/**
* Step 2: "Help me fix this" for server time fail
*
* @return void
*/
protected function servertimefail()
{
return NULL;
}
/**
* Step 2: Self Service - Are there any third party customizations?
*
* @return bool
*/
protected function _thirdPartyCustomizations()
{
return ( count( $this->_thirdPartyApps() ) or count( $this->_thirdPartyPlugins() ) or $this->_thirdPartyTheme() or $this->_thirdPartyEditor() or count( $this->_thirdPartyAds() ) );
}
/**
* Step 2: Self Service - Get third-party applications
*
* @return array
*/
protected function _thirdPartyApps()
{
if ( \IPS\NO_WRITES )
{
return array();
}
$apps = array();
foreach ( \IPS\Application::applications() as $app )
{
if ( $app->enabled and !in_array( $app->directory, \IPS\Application::$ipsApps ) )
{
$apps[] = $app;
}
}
return $apps;
}
/**
* Step 2: Self Service - Get third-party plugins
*
* @return array
*/
protected function _thirdPartyPlugins()
{
if ( \IPS\NO_WRITES )
{
return array();
}
$plugins = array();
foreach ( \IPS\Plugin::plugins() as $plugin )
{
if ( $plugin->enabled )
{
$plugins[] = $plugin;
}
}
return $plugins;
}
/**
* Step 2: Self Service - Has the theme been customised?
*
* @return bool
*/
protected function _thirdPartyTheme()
{
return (bool) \IPS\Db::i()->select( 'COUNT(*)', 'core_theme_templates', 'template_set_id>0' )->first() or \IPS\Db::i()->select( 'COUNT(*)', 'core_theme_css', 'css_set_id>0' )->first();
}
/**
* Step 2: Self Service - Has the editor been customised?
*
* @return bool
*/
protected function _thirdPartyEditor()
{
return ( \IPS\Settings::i()->ckeditor_extraPlugins or \IPS\Settings::i()->ckeditor_toolbars != \IPS\Db::i()->select( 'conf_default', 'core_sys_conf_settings', array( 'conf_key=?', 'ckeditor_toolbars' ) )->first() );
}
/**
* Step 2: Self Service - Get third-party advertisements
*
* @return \IPS\Db\Select
*/
protected function _thirdPartyAds()
{
return \IPS\Db::i()->select( '*' ,'core_advertisements', array( 'ad_active=?', 1 ) );
}
/**
* Step 2: Disable Third Party Customizations
*
* @return void
*/
protected function thirdparty()
{
/* Init */
$disabledApps = array();
$disabledPlugins = array();
$disabledAppNames = array();
$disabledPluginNames = array();
$restoredDefaultTheme = FALSE;
$restoredEditor = FALSE;
$disabledAds = array();
/* Do we need to disable any third party apps/plugins? */
if ( !\IPS\NO_WRITES )
{
/* Loop Apps */
foreach ( $this->_thirdPartyApps() as $app )
{
\IPS\Db::i()->update( 'core_applications', array( 'app_enabled' => 0 ), array( 'app_id=?', $app->id ) );
$disabledApps[] = $app->directory;
$disabledAppNames[ $app->directory ] = $app->_title;
}
/* Look Plugins */
foreach ( $this->_thirdPartyPlugins() as $plugin )
{
\IPS\Db::i()->update( 'core_plugins', array( 'plugin_enabled' => 0 ), array( 'plugin_id=?', $plugin->id ) );
$disabledPlugins[] = $plugin->id;
$disabledPluginNames[ $plugin->id ] = $plugin->_title;
}
if( count( $this->_thirdPartyApps() ) )
{
\IPS\Application::postToggleEnable();
}
if( count( $this->_thirdPartyPlugins() ) )
{
\IPS\Plugin::postToggleEnable( TRUE );
}
}
/* Do we need to restore the default theme? */
if ( $this->_thirdPartyTheme() )
{
$newTheme = new \IPS\Theme;
$newTheme->permissions = \IPS\Member::loggedIn()->member_group_id;
$newTheme->save();
$newTheme->installThemeSettings();
$newTheme->copyResourcesFromSet();
\IPS\Lang::saveCustom( 'core', "core_theme_set_title_" . $newTheme->id, "IPS Default" );
\IPS\Member::loggedIn()->skin = $newTheme->id;
if( \IPS\Member::loggedIn()->acp_skin !== NULL )
{
$_SESSION['old_acp_theme'] = \IPS\Member::loggedIn()->acp_skin;
\IPS\Member::loggedIn()->acp_skin = $newTheme->id;
}
\IPS\Member::loggedIn()->save();
$restoredDefaultTheme = TRUE;
}
/* Do we need to revert the editor? */
if ( $this->_thirdPartyEditor() )
{
\IPS\Data\Store::i()->editorConfiguationToRestore = array(
'extraPlugins' => \IPS\Settings::i()->ckeditor_extraPlugins,
'toolbars' => \IPS\Settings::i()->ckeditor_toolbars,
);
\IPS\Settings::i()->changeValues( array( 'ckeditor_extraPlugins' => '', 'ckeditor_toolbars' => '' ) );
$restoredEditor = TRUE;
}
/* Do we need to disable any thid party ads? */
foreach ( $this->_thirdPartyAds() as $ad )
{
$ad = \IPS\core\Advertisement::constructFromData( $ad );
$ad->active = 0;
$ad->save();
$disabledAds[] = $ad->id;
}
/* Clear cache */
\IPS\Data\Cache::i()->clearAll();
/* Display */
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'support' )->thirdPartyDisabled(
$disabledAppNames,
$disabledPluginNames,
$restoredDefaultTheme ? $newTheme->id : 0,
$restoredEditor,
$disabledAds,
\IPS\Http\Url::internal('app=core&module=support&controller=support&do=thirdpartyEnable')->setQueryString( array(
'enableApps' => implode( ',', $disabledApps ),
'enablePlugins' => implode( ',', $disabledPlugins ),
'deleteTheme' => $restoredDefaultTheme ? $newTheme->id : 0,
'restoreEditor' => intval( $restoredEditor ),
'enableAds' => implode( ',', $disabledAds )
) )
);
}
/**
* Step 2: Re-Enable Third Party Customizations
*
* @return void
*/
protected function thirdpartyEnable()
{
/* Theme */
if ( isset( \IPS\Request::i()->deleteTheme ) and \IPS\Request::i()->deleteTheme )
{
try
{
\IPS\Theme::load( \IPS\Request::i()->deleteTheme )->delete();
}
catch ( \Exception $e ) {}
if( isset( $_SESSION['old_acp_theme'] ) )
{
\IPS\Member::loggedIn()->acp_skin = $_SESSION['old_acp_theme'];
\IPS\Member::loggedIn()->save();
unset( $_SESSION['old_acp_theme'] );
}
}
/* Apps */
foreach ( explode( ',', \IPS\Request::i()->enableApps ) as $app )
{
try
{
\IPS\Db::i()->update( 'core_applications', array( 'app_enabled' => 1 ), array( 'app_directory=?', $app ) );
}
catch ( \Exception $e ) {}
}
/* Plugins */
foreach ( explode( ',', \IPS\Request::i()->enablePlugins ) as $plugin )
{
try
{
\IPS\Db::i()->update( 'core_plugins', array( 'plugin_enabled' => 1 ), array( 'plugin_id=?', $plugin ) );
}
catch ( \Exception $e ) {}
}
if( \IPS\Request::i()->enableApps )
{
\IPS\Application::postToggleEnable();
}
if( \IPS\Request::i()->enablePlugins )
{
\IPS\Plugin::postToggleEnable( TRUE );
}
/* Editor Plugins */
if ( isset( \IPS\Request::i()->restoreEditor ) and \IPS\Request::i()->restoreEditor )
{
$editorConfigutation = \IPS\Data\Store::i()->editorConfiguationToRestore;
\IPS\Settings::i()->changeValues( array( 'ckeditor_extraPlugins' => $editorConfigutation['extraPlugins'], 'ckeditor_toolbars' => $editorConfigutation['toolbars'] ) );
unset( \IPS\Data\Store::i()->editorConfiguationToRestore );
}
/* Ads Ads */
foreach ( explode( ',', \IPS\Request::i()->enableAds ) as $ad )
{
try
{
$ad = \IPS\core\Advertisement::load( $ad );
$ad->active = 1;
$ad->save();
}
catch ( \Exception $e ) {}
}
/* Clear cache */
\IPS\Data\Cache::i()->clearAll();
/* Output */
if ( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->json( 'OK' );
}
else
{
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=core&module=support&controller=support') );
}
}
/**
* Step 3: Contact Support
*
* @param mixed $data Wizard data
* @return string|array
*/
public function _contactSupport( $data )
{
return \IPS\Theme::i()->getTemplate( 'global' )->message( '__ipbmafia__nulling_null_alert', 'error' );
}
}