Version 4.7.6

This commit is contained in:
Neo committed 2025-12-19 16:05:19 -08:00
1 parent 8ba7d43898
commit 7b7404e741
1085 files changed
+30590 -7837

No files matched your search

+10 -6
View File
@@ -96,14 +96,9 @@ class _Admin extends \IPS\Dispatcher\Standard
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'core.css', 'core', 'admin' ) );
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'responsive.css', 'core', 'front' ) );
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'responsive.css', 'core', 'admin' ) );
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js('admin_newFeatures.js', 'core') );
/* JS */
\IPS\Output::i()->globalControllers[] = 'core.admin.core.app';
if ( \IPS\Member::loggedIn()->getFeatureHighlights( FALSE ) )
{
\IPS\Output::i()->globalControllers[] = 'core.admin.core.newFeatures';
}
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'admin.js' ) );
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'jquery/jquery-ui.js', 'core', 'interface' ) );
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'jquery/jquery-touchpunch.js', 'core', 'interface' ) );
@@ -529,6 +524,15 @@ class _Admin extends \IPS\Dispatcher\Standard
*/
public function acpMenuCustom( $url ): ?string
{
if ( !\IPS\Application::appIsEnabled( 'cloud' ) AND $url == 'app=core&module=smartcommunity&controller=cloud' )
{
$url = \IPS\Http\Url::internal( $url, 'admin' );
$title = \IPS\Member::loggedIn()->language()->addToStack( "menu__core_smartcommunity_features" );
return <<<EOF
<a href='{$url}' style="opacity:30%">{$title} <i class="fa fa-lock"></i></a>
EOF;
}
return NULL;
}
@@ -584,7 +588,7 @@ class _Admin extends \IPS\Dispatcher\Standard
}
/* Don't show if installation was less than a month ago */
if ( time() < \IPS\Settings::i()->board_start + ( 86400 * 30 ) )
if ( time() < ( (int) \IPS\Settings::i()->board_start + ( 86400 * 30 ) ) )
{
return false;
}
+26 -2
View File
@@ -56,6 +56,13 @@ class _Api extends \IPS\Dispatcher
* @brief Language
*/
public $language = NULL;
/**
* Can the Response be cached?
*
* @var bool
*/
public bool $cacheResponse = TRUE;
/**
* Init
@@ -94,10 +101,17 @@ class _Api extends \IPS\Dispatcher
/* Set other data */
$this->_setLanguage();
/* We don't want to cache any output for Zapier Requests */
if( \IPS\Request::i()->isZapier() )
{
$this->cacheResponse = FALSE;
}
}
catch ( \IPS\Api\Exception $e )
{
/* Build resonse */
/* Build response */
$response = json_encode( array( 'errorCode' => $e->exceptionCode, 'errorMessage' => $e->getMessage() ), JSON_PRETTY_PRINT );
/* Do we need to log this? */
@@ -408,7 +422,7 @@ class _Api extends \IPS\Dispatcher
*/
protected function _respond( $response, $httpResponseCode, $oauthError=NULL, $log=FALSE )
{
$headers = ( mb_strtolower( $_SERVER['REQUEST_METHOD'] ) == 'get' AND !$this->rawAccessToken ) ? \IPS\Output::getCacheHeaders( time(), 60 ) : \IPS\Output::getNoCacheHeaders();
$headers = $this->canBeCached() ? \IPS\Output::getCacheHeaders( time(), 60 ) : \IPS\Output::getNoCacheHeaders();
if ( $this->rawAccessToken and $oauthError )
{
@@ -422,6 +436,16 @@ class _Api extends \IPS\Dispatcher
\IPS\Output::i()->sendOutput( $response, $httpResponseCode, 'application/json', $headers );
}
/**
* Can this response be cached?
*
* @return bool
*/
protected function canBeCached() : bool
{
return $this->cacheResponse AND mb_strtolower( $_SERVER['REQUEST_METHOD'] ) == 'get' AND !$this->rawAccessToken;
}
/**
* Destructor
+13 -87
View File
@@ -35,9 +35,6 @@ class _Front extends \IPS\Dispatcher\Standard
*/
public function init()
{
/* Get cached page if available */
$this->checkCached();
/* Set up in progress? */
if ( isset( \IPS\Settings::i()->setup_in_progress ) AND \IPS\Settings::i()->setup_in_progress )
{
@@ -81,6 +78,9 @@ class _Front extends \IPS\Dispatcher\Standard
/* Base JS */
static::baseJs();
/* Perform some legacy URL conversions - Need to do this before checking furl in case app name has changed */
static::convertLegacyParameters();
/* Check friendly URL and whether it is correct */
try
{
@@ -99,9 +99,6 @@ class _Front extends \IPS\Dispatcher\Standard
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'app.js' ) );
\IPS\Output::i()->error( 'requested_route_404', '1S160/2', 404, '' );
}
/* Perform some legacy URL conversions*/
static::convertLegacyParameters();
/* Run global init */
try
@@ -245,7 +242,7 @@ class _Front extends \IPS\Dispatcher\Standard
{
\IPS\Output::i()->breadcrumb['module'] = array( \IPS\Http\Url::internal( 'app=' . $this->application->directory . '&module=' . $this->module->key . '&controller=' . $this->module->default_controller, 'front', array_key_exists( $this->module->key, \IPS\Http\Url::furlDefinition() ) ? $this->module->key : NULL ), $this->module->_title );
}
/* Figure out what the global search is */
foreach ( $this->application->extensions( 'core', 'ContentRouter' ) as $object )
{
@@ -257,7 +254,12 @@ class _Front extends \IPS\Dispatcher\Standard
if ( is_subclass_of( $class, 'IPS\Content\Searchable' ) and $class::includeInSiteSearch() and $this->module->key == $class::$module )
{
$type = mb_strtolower( str_replace( '\\', '_', mb_substr( array_pop( $classes ), 4 ) ) );
\IPS\Output::i()->defaultSearchOption = array( $type, "{$type}_pl" );
/* If not the default app, set default search option to current app */
if ( ! mb_stristr( $type, $defaultApplication ) )
{
\IPS\Output::i()->defaultSearchOption = array( $type, "{$type}_pl" );
}
break;
}
}
@@ -388,75 +390,6 @@ class _Front extends \IPS\Dispatcher\Standard
return !\IPS\Member::loggedIn()->group['g_view_board'] and !$this->application->allowGuestAccess( $this->module, $this->controller, \IPS\Request::i()->do );
}
/**
* Check cache for this page
*
* @return void
*/
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 )
{
/* Check whether a 304 Not modified response is appropriate */
try
{
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' ) )
{
return;
}
/* Which language? */
if ( isset( \IPS\Request::i()->cookie['language'] ) )
{
$language = \IPS\Request::i()->cookie['language'];
}
else
{
/* HTTP_ACCEPT_LANGUAGE is only available via http, thus trying to enable FURLs fails as we send out a socket request to test .htaccess */
$language = ( isset( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) ) ? \IPS\Lang::autoDetectLanguage( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) : NULL;
if ( $language === NULL )
{
$language = \IPS\Lang::defaultLanguage();
}
}
/* Which theme? */
$theme = isset( \IPS\Request::i()->cookie['theme'] ) ? \IPS\Request::i()->cookie['theme'] : '';
/* Make sure a session is initiated */
\IPS\Session\Front::i();
/* Get cache */
try
{
$cache = \IPS\Output\Cache::i()->get( 'page_' . md5( (string) \IPS\Request::i()->url() ) . "_{$language}_{$theme}", TRUE );
$sessionId = isset( \IPS\Request::i()->cookie['IPSSessionFront'] ) ? \IPS\Request::i()->cookie['IPSSessionFront'] : \IPS\Session::i()->id;
/* RSS feeds can be shown cached, all other pages contain a cache buster once logged in */
$cache['meta']['httpHeaders'] += \IPS\Output::getCacheHeaders( $cache['meta']['lastUpdated'], \IPS\CACHE_PAGE_TIMEOUT );
$this->_setReferralCookie();
\IPS\Output::i()->sendOutput( str_replace( '{{csrfKey}}', md5( \IPS\SUITE_UNIQUE_KEY . '&& 0&' . $sessionId ), $cache['output'] ), $cache['meta']['code'], $cache['meta']['contentType'], $cache['meta']['httpHeaders'], FALSE, TRUE );
}
catch ( \OutOfRangeException $e ) {}
}
}
/**
* Perform some legacy URL parameter conversions
*
@@ -738,7 +671,7 @@ class _Front extends \IPS\Dispatcher\Standard
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 ] ), '/' ) . '/' );
$sitemapUrl = ( new \IPS\Sitemap )->sitemapUrl;
$content = <<<FILE
# Rules for Invision Community (https://invisioncommunity.com)
User-Agent: *
@@ -751,6 +684,7 @@ Disallow: {$path}online/
Disallow: {$path}discover/
Disallow: {$path}leaderboard/
Disallow: {$path}search/
Disallow: {$path}tags/
Disallow: {$path}*?advancedSearchForm=
Disallow: {$path}register/
Disallow: {$path}lostpassword/
@@ -767,17 +701,9 @@ 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}
Sitemap: {$sitemapUrl}
FILE;
}
return $content;
}
+3 -17
View File
@@ -120,23 +120,9 @@ class _GraphQL extends Api
$variables = $json['variables'];
}
}
/* Execute! */
$result = \GraphQL\GraphQL::executeQuery(
new \GraphQL\Type\Schema([
'query' => \IPS\Api\GraphQL\TypeRegistry::query(),
'mutation' => \IPS\Api\GraphQL\TypeRegistry::mutation()
]),
$query,
NULL, // $rootValue
[
'member' => \IPS\Member::loggedIn()
], // $context
$variables
);
/* Convert result into JSON and send */
$output = $result->toArray( ( \IPS\IN_DEV OR \IPS\DEBUG_GRAPHQL ) ? \GraphQL\Error\DebugFlag::INCLUDE_DEBUG_MESSAGE | \GraphQL\Error\DebugFlag::INCLUDE_TRACE : false );
$output = \IPS\Api\GraphQL::execute( $query, $variables );
\IPS\Member::loggedIn()->language()->parseOutputForDisplay( $output );
$this->_respond( json_encode( $output, JSON_PRETTY_PRINT ), 200 );