Version 5.0.0 beta 4
This commit is contained in:
1 parent
e86153356a
commit
2f24f9de48
276 files changed
+8614
-6044
No files matched your search
+145
-25
@@ -291,6 +291,11 @@ class Output
|
||||
* @brief Data which were loaded via the GraphQL framework, but which have to be immediately available, rather then via later AJAX requests
|
||||
*/
|
||||
public array $graphData = [];
|
||||
|
||||
/**
|
||||
* @brief A custom cache DateTime object set to UTC
|
||||
*/
|
||||
protected static bool|null|DateTime $cacheDate = NULL;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@@ -523,6 +528,17 @@ class Output
|
||||
return $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store any custom DateTime for cache headers
|
||||
*
|
||||
* @param DateTime|bool $date
|
||||
* @return void
|
||||
*/
|
||||
public static function setCacheTime( DateTime|bool $date=false ): void
|
||||
{
|
||||
static::$cacheDate = $date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve cache headers
|
||||
*
|
||||
@@ -532,10 +548,43 @@ class Output
|
||||
*/
|
||||
public static function getCacheHeaders( int $lastModified, int $cacheSeconds ): array
|
||||
{
|
||||
/* The default is null, so if it is to false from setCacheTime, we should not cache */
|
||||
if ( static::$cacheDate === false )
|
||||
{
|
||||
return static::getNoCacheHeaders();
|
||||
}
|
||||
|
||||
$expires = DateTime::ts( ( time() + $cacheSeconds ), TRUE );
|
||||
if ( static::$cacheDate instanceof \DateTime )
|
||||
{
|
||||
$expires = static::$cacheDate;
|
||||
$cacheSeconds = $expires->getTimestamp() - time();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set the cache date to the expiration date in case anything intercepts the output process and checks the cacheDate */
|
||||
static::$cacheDate = $expires;
|
||||
}
|
||||
|
||||
if ( \IPS\CIC or \IPS\IN_DEV )
|
||||
{
|
||||
return array(
|
||||
'Date' => DateTime::ts( time(), TRUE )->rfc1123(),
|
||||
'Last-Modified' => DateTime::ts( $lastModified, TRUE )->rfc1123(),
|
||||
'Expires' => $expires->rfc1123(),
|
||||
'Cache-Control' => implode( ', ', [
|
||||
'max-age=0', // No cache for the browser [https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#response_directives]
|
||||
'public', // Public cache
|
||||
's-maxage=' . $cacheSeconds, // Cache for the CDN [https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#response_directives]
|
||||
'stale-if-error' // Allow the CDN to serve stale content if there is an error
|
||||
] )
|
||||
);
|
||||
}
|
||||
|
||||
return array(
|
||||
'Date' => DateTime::ts( time(), TRUE )->rfc1123(),
|
||||
'Last-Modified' => DateTime::ts( $lastModified, TRUE )->rfc1123(),
|
||||
'Expires' => DateTime::ts( ( time() + $cacheSeconds ), TRUE )->rfc1123(),
|
||||
'Expires' => $expires->rfc1123(),
|
||||
'Cache-Control' => 'no-cache="Set-Cookie", max-age=' . $cacheSeconds . ", public, s-maxage=" . $cacheSeconds . ", stale-while-revalidate, stale-if-error",
|
||||
);
|
||||
}
|
||||
@@ -799,7 +848,7 @@ class Output
|
||||
|
||||
/* Log */
|
||||
$level = intval( substr( $code, 0, 1 ) );
|
||||
if( !Session::i()->userAgent->spider )
|
||||
if( !Session::i()->userAgent->bot )
|
||||
{
|
||||
if( $code and Settings::i()->error_log_level and $level >= Settings::i()->error_log_level )
|
||||
{
|
||||
@@ -890,6 +939,79 @@ class Output
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Can this output be cached by CDN?
|
||||
*
|
||||
* @param string $contentType
|
||||
* @param bool $checkCachePageTimeout
|
||||
* @return bool
|
||||
*/
|
||||
public function isCacheable( string $contentType='text/html', bool $checkCachePageTimeout = true ): bool
|
||||
{
|
||||
/* Have we got a value for the default cache timeout? */
|
||||
if ( $checkCachePageTimeout and ! \IPS\CACHE_PAGE_TIMEOUT )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Have we set a per-page cache timeout of false, which means we don't want to cache? */
|
||||
if ( static::$cacheDate === false )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if ( static::$cacheDate instanceof DateTime )
|
||||
{
|
||||
/* Or have we set a specific cache date and it's in the past? */
|
||||
$cacheSeconds = static::$cacheDate->getTimestamp() - time();
|
||||
if ( $cacheSeconds <= 0 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Are we logged in? */
|
||||
if ( Member::loggedIn()->member_id )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Are we using the legacy pageCaching flag? */
|
||||
if ( ! $this->pageCaching )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Do we have a noCache cookie set? */
|
||||
if ( isset( Request::i()->cookie['noCache'] ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Do we have a CSRF key? */
|
||||
if ( isset( Request::i()->csrfKey ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check the request method */
|
||||
if ( ! in_array( mb_strtolower( $_SERVER['REQUEST_METHOD'] ), [ 'get', 'head' ] ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! in_array( $contentType, ['text/html', 'text/xml', 'application/manifest+json' ] ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( Dispatcher::hasInstance() and class_exists( 'IPS\Dispatcher', FALSE ) and Dispatcher::i()->controllerLocation !== 'front' )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Flag to bypass CSRF IN_DEV check
|
||||
*/
|
||||
@@ -945,36 +1067,18 @@ class Output
|
||||
$this->parseFileObjectUrls( $output );
|
||||
}
|
||||
|
||||
/* Combine some common checks for re-use */
|
||||
$canCache = function( $contentType, $obj ) {
|
||||
if( $obj->pageCaching and
|
||||
( mb_strtolower( $_SERVER['REQUEST_METHOD'] ) == 'get' OR mb_strtolower( $_SERVER['REQUEST_METHOD'] ) == 'head' ) and // Is a HTTP GET/HEAD request (don't cache output for POSTs)
|
||||
( $contentType == 'text/html' or $contentType == 'text/xml' or $contentType == 'application/manifest+json' ) and // Output is HTML, XML or [PWA] application manifest (don't cache JSON output, etc)
|
||||
Dispatcher::hasInstance() and class_exists( 'IPS\Dispatcher', FALSE ) and Dispatcher::i()->controllerLocation === 'front' // Is a normal, front-end page (necessary to know if user is logged in)
|
||||
)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
};
|
||||
|
||||
if (
|
||||
CACHE_PAGE_TIMEOUT and // Page caching is enabled
|
||||
$cacheThisPage and // Some pages can specify not to be cached (for example, when displaying a cached page, you don't want it recached)
|
||||
!isset( Request::i()->cookie['noCache'] ) and // A noCache cookie might get set to not cache a particular guest (for example, if they have added items to their cart in the store)
|
||||
$canCache( $contentType, $this ) and // Common checks, see above
|
||||
!isset( Request::i()->csrfKey ) and // CSRF key isn't present (which would be like a POST request)
|
||||
!Member::loggedIn()->member_id // User is not logged in
|
||||
) {
|
||||
/* Can we cache this page to a CDN? */
|
||||
if( $cacheThisPage and $this->isCacheable( $contentType ) )
|
||||
{
|
||||
/* Add caching headers */
|
||||
if( !isset( $httpHeaders['Cache-Control'] ) )
|
||||
{
|
||||
$httpHeaders += Output::getCacheHeaders( time(), CACHE_PAGE_TIMEOUT);
|
||||
}
|
||||
}
|
||||
/* Send no-cache headers if we got to this point without any cache-control headers being set, or page caching is forced off */
|
||||
elseif( !isset( $httpHeaders['Cache-Control'] ) OR !$this->pageCaching )
|
||||
elseif( !isset( $httpHeaders['Cache-Control'] ) )
|
||||
{
|
||||
/* Send no-cache headers if we got to this point without any cache-control headers being set, or page caching is forced off */
|
||||
$httpHeaders += Output::getNoCacheHeaders();
|
||||
}
|
||||
|
||||
@@ -1154,6 +1258,22 @@ class Output
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Should we reduce the number of links in the HTML for SEO purposes?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function reduceLinks(): bool
|
||||
{
|
||||
if ( ! Member::loggedIn()->member_id and Settings::i()->seo_reduce_links )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove any comment tags that were inserted in the middle of an HTML tag
|
||||
*
|
||||
|
||||
Reference in new issue
Block a user