Version 4.7.0
This commit is contained in:
1 parent
517a5e1f70
commit
8ba7d43898
1933 files changed
+65613
-11332
No files matched your search
@@ -206,7 +206,12 @@ class _Admin extends \IPS\Dispatcher\Standard
|
||||
{
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2S107/1', 403, '' );
|
||||
}
|
||||
|
||||
|
||||
if( ! \IPS\Application::appIsEnabled( $this->application->directory ) )
|
||||
{
|
||||
\IPS\Output::i()->error( 'requested_route_404', '2S107/5', 404, '' );
|
||||
}
|
||||
|
||||
/* Support is not available for demos */
|
||||
if ( \IPS\DEMO_MODE AND $this->module->application === 'core' AND $this->module->key === 'support' )
|
||||
{
|
||||
@@ -515,7 +520,18 @@ class _Admin extends \IPS\Dispatcher\Standard
|
||||
|
||||
return $this->acpTabOrder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Display a link in a custom format
|
||||
*
|
||||
* @param string $url The URL from the menu system
|
||||
* @return string|null
|
||||
*/
|
||||
public function acpMenuCustom( $url ): ?string
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do we have permission to use this module?
|
||||
*
|
||||
@@ -534,13 +550,77 @@ class _Admin extends \IPS\Dispatcher\Standard
|
||||
* @param string $key Permission Key
|
||||
* @param \IPS\Application|null $app Application (NULL will default to current)
|
||||
* @param \IPS\Module|string|null $module Module (NULL will default to current)
|
||||
* @param boolean $return Return boolean (true/false) instead of throwing an error
|
||||
* @return void
|
||||
*/
|
||||
public function checkAcpPermission( $key, $app=NULL, $module=NULL )
|
||||
public function checkAcpPermission( $key, $app=NULL, $module=NULL, $return=FALSE )
|
||||
{
|
||||
if ( !\IPS\Member::loggedIn()->hasAcpRestriction( ( $app ?: $this->application ), ( $module ?: $this->module ), $key ) )
|
||||
{
|
||||
if ( $return )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
\IPS\Output::i()->error( 'no_module_permission', '2S107/2', 403, '' );
|
||||
}
|
||||
|
||||
if ( $return )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show switch link
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
final public static function showSwitchLink(): bool
|
||||
{
|
||||
if ( \IPS\CIC )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Don't show if installation was less than a month ago */
|
||||
if ( time() < \IPS\Settings::i()->board_start + ( 86400 * 30 ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( \IPS\Request::i()->cookie['acpLinkSnooze'] ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
$value = json_decode( \IPS\Request::i()->cookie['acpLinkSnooze'], true );
|
||||
|
||||
if ( $value['hits'] < 3 )
|
||||
{
|
||||
/* Show every 30 days */
|
||||
if ( time() < ( $value['lastClick'] + ( 86400 * 30 ) ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if ( $value['hits'] < 9 )
|
||||
{
|
||||
/* Show every 60 days */
|
||||
if ( time() < ( $value['lastClick'] + ( 86400 * 60 ) ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Show every 90 days */
|
||||
if ( time() < ( $value['lastClick'] + ( 86400 * 90 ) ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -408,7 +408,7 @@ class _Api extends \IPS\Dispatcher
|
||||
*/
|
||||
protected function _respond( $response, $httpResponseCode, $oauthError=NULL, $log=FALSE )
|
||||
{
|
||||
$headers = ( mb_strtolower( $_SERVER['REQUEST_METHOD'] ) == 'get' ) ? \IPS\Output::getCacheHeaders( time(), 60 ) : \IPS\Output::getNoCacheHeaders();
|
||||
$headers = ( mb_strtolower( $_SERVER['REQUEST_METHOD'] ) == 'get' AND !$this->rawAccessToken ) ? \IPS\Output::getCacheHeaders( time(), 60 ) : \IPS\Output::getNoCacheHeaders();
|
||||
|
||||
if ( $this->rawAccessToken and $oauthError )
|
||||
{
|
||||
|
||||
@@ -31,6 +31,15 @@ abstract class _Controller
|
||||
* @brief Is this for displaying "content"? Affects if advertisements may be shown
|
||||
*/
|
||||
public $isContentPage = TRUE;
|
||||
|
||||
/**
|
||||
* @brief These properties are used to specify datalayer context properties.
|
||||
*
|
||||
* @example array(
|
||||
'community_area' => array( 'value' => 'search', 'odkUpdate' => 'true' )
|
||||
* )
|
||||
*/
|
||||
public static $dataLayerContext = array();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@@ -82,6 +91,14 @@ abstract class _Controller
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
if ( !empty( static::$dataLayerContext ) AND \IPS\Settings::i()->core_datalayer_enabled AND !\IPS\Request::i()->isAjax() )
|
||||
{
|
||||
foreach ( static::$dataLayerContext as $property => $data )
|
||||
{
|
||||
\IPS\core\DataLayer::i()->addContextProperty( $property, $data['value'], $data['odkUpdate'] ?? false );
|
||||
}
|
||||
}
|
||||
|
||||
if( \IPS\Request::i()->do and preg_match( '/^[a-zA-Z\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', \IPS\Request::i()->do ) )
|
||||
{
|
||||
if ( method_exists( $this, \IPS\Request::i()->do ) or method_exists( $this, '__call' ) )
|
||||
|
||||
@@ -26,7 +26,7 @@ abstract class _Dispatcher
|
||||
* @brief Singleton Instance
|
||||
*/
|
||||
protected static $instance = NULL;
|
||||
|
||||
|
||||
/**
|
||||
* Check if a dispatcher instance is available
|
||||
*
|
||||
@@ -170,7 +170,23 @@ abstract class _Dispatcher
|
||||
else
|
||||
{
|
||||
/* Just prefetch this to save a query later */
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->globalTemplate( \IPS\Output::i()->title, \IPS\Output::i()->output, array( 'app' => \IPS\Dispatcher::i()->application->directory, 'module' => \IPS\Dispatcher::i()->module->key, 'controller' => \IPS\Dispatcher::i()->controller ) ), 200, 'text/html' );
|
||||
\IPS\Output::i()->sendOutput( \IPS\Theme::i()->getTemplate( 'global', 'core' )->globalTemplate( \IPS\Output::i()->title, \IPS\Output::i()->output, $this->getLocationData() ), 200, 'text/html' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of data representing the user's current location
|
||||
* This gets passed to the templates in order to apply some attributes to the body tag
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getLocationData()
|
||||
{
|
||||
return array(
|
||||
'app' => \IPS\Dispatcher::i()->application->directory,
|
||||
'module' => \IPS\Dispatcher::i()->module->key,
|
||||
'controller' => \IPS\Dispatcher::i()->controller,
|
||||
'id' => \IPS\Request::i()->id ? (int) \IPS\Request::i()->id : NULL
|
||||
);
|
||||
}
|
||||
}
|
||||
+216
-85
@@ -191,83 +191,15 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
|
||||
/* Do we need more info from the member or do they need to validate? */
|
||||
|
||||
/* This controllers should always be accessible, no matter if the member is awaiting validation or needs to set up the email or name */
|
||||
$legalControllers = array( 'privacy', 'contact', 'terms', 'embed', 'metatags', 'store', 'checkout', 'subscriptions' );
|
||||
/* These controllers should always be accessible, no matter if the member is awaiting validation or needs to set up the email or name */
|
||||
$legalControllers = array( 'privacy', 'contact', 'terms', 'embed', 'metatags', 'subscriptions', 'serviceworker', 'settings' );
|
||||
|
||||
/* Do we need more info from the member or do they need to validate? */
|
||||
if( \IPS\Member::loggedIn()->member_id and $this->controller !== 'language' and $this->controller !== 'theme' and $this->controller !== 'ajax' and !\in_array( $this->controller, $legalControllers ) )
|
||||
{
|
||||
/* Need their name or email... */
|
||||
if( ( \IPS\Member::loggedIn()->real_name === '' or !\IPS\Member::loggedIn()->email ) and $this->controller !== 'register' and $this->controller !== 'login' )
|
||||
if ( $url = static::doMemberCheck() )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=register&do=complete' )->setQueryString( 'ref', base64_encode( \IPS\Request::i()->url() ) ) );
|
||||
}
|
||||
/* Need them to validate... */
|
||||
elseif( \IPS\Member::loggedIn()->members_bitoptions['validating'] and $this->controller !== 'register' and $this->controller !== 'login' and $this->controller != 'redirect' )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=register&do=validating', 'front', 'register' ) );
|
||||
}
|
||||
/* Need them to reconfirm terms/privacy policy... */
|
||||
elseif ( ( \IPS\Member::loggedIn()->members_bitoptions['must_reaccept_privacy'] or \IPS\Member::loggedIn()->members_bitoptions['must_reaccept_terms'] ) and $this->controller !== 'register' and $this->controller !== 'ajax' )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=register&do=reconfirm', 'front', 'register' )->setQueryString( 'ref', base64_encode( \IPS\Request::i()->url() ) ) );
|
||||
}
|
||||
/* Have required profile actions that need completing */
|
||||
else if ( \IPS\Settings::i()->quick_register AND !\IPS\Member::loggedIn()->members_bitoptions['profile_completed'] AND !\in_array( $this->controller, array( 'register', 'login', 'redirect', 'ajax', 'settings', 'checkout', 'pixabay', 'editor' ) ) AND $completion = \IPS\Member::loggedIn()->profileCompletion() AND \count( $completion['required'] ) )
|
||||
{
|
||||
foreach( $completion['required'] AS $id => $completed )
|
||||
{
|
||||
if ( $completed === FALSE )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=core&module=system&controller=register&do=finish&_new=1", 'front', 'register' )->setQueryString( 'ref', base64_encode( \IPS\Request::i()->url() ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Need to set up MFA... */
|
||||
if ( !\in_array( $this->controller, array( 'register', 'login', 'redirect', 'ajax', 'settings', 'embed' ) ) )
|
||||
{
|
||||
$haveAcceptableHandlers = FALSE;
|
||||
$haveConfiguredHandler = FALSE;
|
||||
foreach ( \IPS\MFA\MFAHandler::handlers() as $key => $handler )
|
||||
{
|
||||
if ( $handler->isEnabled() and $handler->memberCanUseHandler( \IPS\Member::loggedIn() ) )
|
||||
{
|
||||
$haveAcceptableHandlers = TRUE;
|
||||
if ( $handler->memberHasConfiguredHandler( \IPS\Member::loggedIn() ) )
|
||||
{
|
||||
$haveConfiguredHandler = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !$haveConfiguredHandler and $haveAcceptableHandlers )
|
||||
{
|
||||
if ( \IPS\Settings::i()->mfa_required_groups == '*' or \IPS\Member::loggedIn()->inGroup( explode( ',', \IPS\Settings::i()->mfa_required_groups ) ) )
|
||||
{
|
||||
if ( \IPS\Settings::i()->mfa_required_prompt === 'immediate' )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=settings&do=initialMfa', 'front', 'settings' )->setQueryString( 'ref', base64_encode( \IPS\Request::i()->url() ) ) );
|
||||
}
|
||||
}
|
||||
elseif ( \IPS\Settings::i()->mfa_optional_prompt === 'immediate' and !\IPS\Member::loggedIn()->members_bitoptions['security_questions_opt_out'] )
|
||||
{
|
||||
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=core&module=system&controller=settings&do=initialMfa', 'front', 'settings' )->setQueryString( 'ref', base64_encode( \IPS\Request::i()->url() ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Need to reset password */
|
||||
if ( $this->controller !== 'settings' AND ( !isset( \IPS\Request::i()->area ) OR \IPS\Request::i()->area !== 'password' ) )
|
||||
{
|
||||
foreach( \IPS\Login::methods() AS $method )
|
||||
{
|
||||
if ( $url = $method->forcePasswordResetUrl( \IPS\Member::loggedIn(), \IPS\Request::i()->url() ) )
|
||||
{
|
||||
\IPS\Output::i()->redirect( $url );
|
||||
}
|
||||
}
|
||||
\IPS\Output::i()->redirect( $url );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,7 +219,10 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
{
|
||||
\IPS\Output::i()->error( 'requested_route_404', '2S160/5', 404, '' );
|
||||
}
|
||||
|
||||
|
||||
/* Set up isAnonymous variable for realtime */
|
||||
\IPS\Output::i()->jsVars['isAnonymous'] = (bool) \IPS\Member::loggedIn()->isOnlineAnonymously();
|
||||
|
||||
/* Stuff for output */
|
||||
if ( !\IPS\Request::i()->isAjax() )
|
||||
{
|
||||
@@ -356,7 +291,7 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
if ( \IPS\Settings::i()->use_friendly_urls )
|
||||
{
|
||||
$url = \IPS\Request::i()->url();
|
||||
|
||||
|
||||
/* Redirect to the "correct" friendly URL if there is one */
|
||||
if ( !\IPS\Request::i()->isAjax() and mb_strtolower( $_SERVER['REQUEST_METHOD'] ) == 'get' and !\IPS\ENFORCE_ACCESS )
|
||||
{
|
||||
@@ -368,13 +303,23 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
$correctUrl = $url->correctFriendlyUrl();
|
||||
}
|
||||
|
||||
/* If they are accessing "index.php/whatever", we want "index.php?/whatever */
|
||||
if ( !( $correctUrl instanceof \IPS\Http\Url ) and $url instanceof \IPS\Http\Url\Internal and mb_strpos( $url->data[ \IPS\Http\Url::COMPONENT_PATH ], '/index.php/' ) !== FALSE )
|
||||
|
||||
if ( !( $correctUrl instanceof \IPS\Http\Url ) and $url instanceof \IPS\Http\Url\Internal )
|
||||
{
|
||||
$pathFromBaseUrl = ltrim( mb_substr( $url->data[ \IPS\Http\Url::COMPONENT_PATH ], mb_strlen( \IPS\Http\Url::internal('')->data[ \IPS\Http\Url::COMPONENT_PATH ] ) ), '/' );
|
||||
if ( mb_substr( $pathFromBaseUrl, 0, 10 ) === 'index.php/' )
|
||||
|
||||
/* If they are accessing "index.php/whatever", we want "index.php?/whatever */
|
||||
if ( mb_strpos( $url->data[ \IPS\Http\Url::COMPONENT_PATH ], '/index.php/' ) !== FALSE )
|
||||
{
|
||||
$correctUrl = \IPS\Http\Url\Friendly::friendlyUrlFromComponent( 0, trim( mb_substr( $pathFromBaseUrl, 10 ), '/' ), $url->queryString );
|
||||
if ( mb_substr( $pathFromBaseUrl, 0, 10 ) === 'index.php/' )
|
||||
{
|
||||
$correctUrl = \IPS\Http\Url\Friendly::friendlyUrlFromComponent( 0, trim( mb_substr( $pathFromBaseUrl, 10 ), '/' ), $url->queryString );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If necessary, return any special cases like the robots.txt file */
|
||||
$this->customResponse( $pathFromBaseUrl );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -451,16 +396,20 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
protected function checkCached()
|
||||
{
|
||||
/* If this is a guest and there's a full cached page, we can serve that */
|
||||
if( mb_strtolower( $_SERVER['REQUEST_METHOD'] ) == 'get' and !isset( \IPS\Request::i()->csrfKey ) and !isset( \IPS\Request::i()->_mfaLogin ) and !\IPS\Session\Front::loggedIn() and !isset( \IPS\Request::i()->cookie['noCache'] ) and \IPS\CACHE_PAGE_TIMEOUT )
|
||||
if( mb_strtolower( $_SERVER['REQUEST_METHOD'] ) == 'get' AND !isset( \IPS\Request::i()->csrfKey ) AND !isset( \IPS\Request::i()->_mfaLogin ) AND !\IPS\Session\Front::loggedIn() AND !isset( \IPS\Request::i()->cookie['noCache'] ) AND \IPS\CACHE_PAGE_TIMEOUT )
|
||||
{
|
||||
/* Check whether a 304 Not modified response is appropriate */
|
||||
if( !empty( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) AND ( new \IPS\DateTime( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) )->getTimestamp() > ( time() - \IPS\CACHE_PAGE_TIMEOUT ) )
|
||||
try
|
||||
{
|
||||
/* This is intentionally using PHP methods to avoid database connections */
|
||||
$this->destruct = false;
|
||||
header('HTTP/1.1 304 Not Modified' );
|
||||
exit;
|
||||
if( !empty( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) AND ( new \IPS\DateTime( \rtrim( $_SERVER['HTTP_IF_MODIFIED_SINCE'], ';' ) ) )->getTimestamp() > ( time() - \IPS\CACHE_PAGE_TIMEOUT ) )
|
||||
{
|
||||
/* This is intentionally using PHP methods to avoid database connections */
|
||||
$this->destruct = false;
|
||||
header('HTTP/1.1 304 Not Modified' );
|
||||
exit;
|
||||
}
|
||||
}
|
||||
catch ( \Exception $e ) { }
|
||||
|
||||
/* Only check the output cache if it is enabled */
|
||||
if( empty( \IPS\OUTPUT_CACHE_METHOD ) OR ( !empty( \IPS\OUTPUT_CACHE_METHOD ) AND \IPS\OUTPUT_CACHE_METHOD == 'None' ) )
|
||||
@@ -660,18 +609,24 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
}
|
||||
}
|
||||
|
||||
/* Do things if we're actively using the easy theme editor */
|
||||
\IPS\Theme::easyModePreOutput();
|
||||
|
||||
/* Meta tags */
|
||||
\IPS\Output::i()->buildMetaTags();
|
||||
|
||||
/* Check MFA */
|
||||
$this->checkMfa();
|
||||
|
||||
/* Check Alerts */
|
||||
$this->checkAlerts();
|
||||
|
||||
/* Finish */
|
||||
parent::finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check MFA to see if we need to supply a code
|
||||
* Check MFA to see if we need to supply a code. If the member elected to cancel, cancel (and redirect) here
|
||||
*
|
||||
* @param boolean $return Return any HTML (true) or add to Output (false)
|
||||
*
|
||||
@@ -685,6 +640,37 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
$device = \IPS\Member\Device::loadOrCreate( $member, FALSE );
|
||||
if ( $output = \IPS\MFA\MFAHandler::accessToArea( 'core', $device->known ? 'AuthenticateFrontKnown' : 'AuthenticateFront', \IPS\Request::i()->url(), $member ) )
|
||||
{
|
||||
/* Did we just cancel? */
|
||||
if ( \IPS\Request::i()->_mfaCancel and ( ! \IPS\Member::loggedIn()->member_id or ( \IPS\Member::loggedIn()->member_id === $member->member_id ) ) )
|
||||
{
|
||||
/* We don't need this until we re-enter the MFA flow again */
|
||||
unset( $_SESSION['processing2FA'] );
|
||||
|
||||
/* Is MFA required for this member? */
|
||||
$mfaRequired = \IPS\Settings::i()->mfa_required_groups === '*' or $member->inGroup( explode( ',', \IPS\Settings::i()->mfa_required_groups ) );
|
||||
|
||||
/* Does this member require MFA upon login? */
|
||||
$logout = \IPS\Settings::i()->mfa_required_prompt === 'immediate' and $mfaRequired;
|
||||
|
||||
/* Can they see this page without MFA? */
|
||||
if ( !$mfaRequired OR ( $logout and $this->application->allowGuestAccess( $this->module, $this->controller, \IPS\Request::i()->do ) ) )
|
||||
{
|
||||
$redirectUrl = \IPS\Request::i()->url()->stripQueryString([ '_mfaCancel', '_mfaLogin', '_fromLogin', 'csrfKey' ]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$redirectUrl = \IPS\Http\Url::internal( '' );
|
||||
}
|
||||
|
||||
if ( $logout )
|
||||
{
|
||||
\IPS\Login::logout( $redirectUrl );
|
||||
$redirectUrl = $redirectUrl->setQueryString( '_fromLogout', 1 );
|
||||
}
|
||||
|
||||
\IPS\Output::i()->redirect( $redirectUrl );
|
||||
}
|
||||
|
||||
if ( $return )
|
||||
{
|
||||
return $output;
|
||||
@@ -699,6 +685,103 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a robots.txt file if configured to do so
|
||||
*
|
||||
* @param string $pathFromBaseUrl
|
||||
*/
|
||||
public function customResponse( string $pathFromBaseUrl )
|
||||
{
|
||||
if ( $pathFromBaseUrl === 'robots.txt' )
|
||||
{
|
||||
$this->robotsTxt();
|
||||
}
|
||||
else if ( \IPS\core\IndexNow::i()->isEnabled() AND $pathFromBaseUrl === \IPS\core\IndexNow::i()->getKeyFileName() )
|
||||
{
|
||||
$this->indexNow();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the IndexNow key.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function indexNow()
|
||||
{
|
||||
\IPS\Output::i()->sendOutput( \IPS\core\IndexNow::i()->getKeyfileContent(), 200, 'text/plain' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the robots.txt files
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function robotsTxt()
|
||||
{
|
||||
if ( \IPS\Settings::i()->robots_txt == 'default' )
|
||||
{
|
||||
\IPS\Output::i()->sendOutput( static::robotsTxtRules(), 200, 'text/plain' );
|
||||
}
|
||||
else if ( \IPS\Settings::i()->robots_txt != 'off' )
|
||||
{
|
||||
\IPS\Output::i()->sendOutput( \IPS\Settings::i()->robots_txt, 200, 'text/plain' );
|
||||
}
|
||||
throw new \OutOfRangeException;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the text for the robots.txt file
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function robotsTxtRules(): string
|
||||
{
|
||||
$path = str_replace( '//', '/', '/' . trim( str_replace( 'robots.txt', '', \IPS\Http\Url::createFromString( \IPS\Http\Url::baseUrl() )->data[ \IPS\Http\Url::COMPONENT_PATH ] ), '/' ) . '/' );
|
||||
|
||||
$content = <<<FILE
|
||||
# Rules for Invision Community (https://invisioncommunity.com)
|
||||
User-Agent: *
|
||||
# Block pages with no unique content
|
||||
Disallow: {$path}startTopic/
|
||||
Disallow: {$path}discover/unread/
|
||||
Disallow: {$path}markallread/
|
||||
Disallow: {$path}staff/
|
||||
Disallow: {$path}online/
|
||||
Disallow: {$path}discover/
|
||||
Disallow: {$path}leaderboard/
|
||||
Disallow: {$path}search/
|
||||
Disallow: {$path}*?advancedSearchForm=
|
||||
Disallow: {$path}register/
|
||||
Disallow: {$path}lostpassword/
|
||||
Disallow: {$path}login/
|
||||
|
||||
# Block faceted pages and 301 redirect pages
|
||||
Disallow: {$path}*?sortby=
|
||||
Disallow: {$path}*?filter=
|
||||
Disallow: {$path}*?tab=
|
||||
Disallow: {$path}*?do=
|
||||
Disallow: {$path}*ref=
|
||||
Disallow: {$path}*?forumId*
|
||||
|
||||
# Block profile pages as these have little unique value, consume a lot of crawl time and contain hundreds of 301 links
|
||||
Disallow: {$path}profile/
|
||||
|
||||
FILE;
|
||||
|
||||
if ( \IPS\Settings::i()->sitemap_url )
|
||||
{
|
||||
$siteMapUrl = ( \IPS\Settings::i()->sitemap_url ) ? rtrim( \IPS\Settings::i()->sitemap_url, '/' ) : rtrim( \IPS\Settings::i()->base_url, '/' ) . '/sitemap.php';
|
||||
$content .= <<<FILE
|
||||
|
||||
# Sitemap URL
|
||||
Sitemap: {$siteMapUrl}
|
||||
FILE;
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the basic javascript files every page needs
|
||||
*
|
||||
@@ -712,6 +795,10 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
if ( !\IPS\Request::i()->isAjax() )
|
||||
{
|
||||
\IPS\Output::i()->globalControllers[] = 'core.front.core.app';
|
||||
if ( \IPS\Settings::i()->core_datalayer_enabled )
|
||||
{
|
||||
\IPS\Output::i()->globalControllers[] = 'core.front.core.dataLayer';
|
||||
}
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front.js' ) );
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'front_core.js', 'core', 'front' ) );
|
||||
|
||||
@@ -777,4 +864,48 @@ class _Front extends \IPS\Dispatcher\Standard
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Do Member Check
|
||||
*
|
||||
* @return \IPS\Http\Url|NULL
|
||||
*/
|
||||
protected static function doMemberCheck(): ?\IPS\Http\Url
|
||||
{
|
||||
foreach( \IPS\Application::applications() AS $app )
|
||||
{
|
||||
if ( $url = $app->doMemberCheck() )
|
||||
{
|
||||
return $url;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function checkAlerts()
|
||||
{
|
||||
/* Don't get in the way of validating members */
|
||||
if ( \IPS\Member::loggedIn()->members_bitoptions['validating'] )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Don't get in the way of the ModCP, registering, logging in, etc */
|
||||
$ignoreControllers = [ 'modcp', 'register', 'login', 'redirect' ];
|
||||
if( !\IPS\Request::i()->isAjax() and !\in_array( $this->controller, $ignoreControllers ) AND $alert = \IPS\core\Alerts\Alert::getNextAlertForMember( \IPS\Member::loggedIn() ) )
|
||||
{
|
||||
$alert->viewed( \IPS\Member::loggedIn() );
|
||||
|
||||
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'styles/alerts.css', 'core', 'front' ) );
|
||||
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'alerts', 'core', 'front' )->alertModal( $alert, $url = base64_encode( \IPS\Request::i()->url() ) );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user