Created
June 1, 2018 03:51
-
-
Save sminnee/83f607a09c27b1c0dc59d71b819fa401 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/control/Controller.php b/control/Controller.php | |
| index 274b567..484c06f 100644 | |
| --- a/control/Controller.php | |
| +++ b/control/Controller.php | |
| @@ -502,7 +502,7 @@ class Controller extends RequestHandler implements TemplateGlobalProvider { | |
| */ | |
| public function redirectBack() { | |
| // Don't cache the redirect back ever | |
| - HTTPCacheControl::singleton()->disableCaching(); | |
| + HTTPCacheControl::singleton()->disableCache(true); | |
| $url = null; | |
| diff --git a/control/Director.php b/control/Director.php | |
| index b98731e..095e700 100644 | |
| --- a/control/Director.php | |
| +++ b/control/Director.php | |
| @@ -384,7 +384,7 @@ class Director implements TemplateGlobalProvider { | |
| try { | |
| $result = $controllerObj->handleRequest($request, $model); | |
| } catch(SS_HTTPResponse_Exception $responseException) { | |
| - HTTPCacheControl::singleton()->disableCaching(); | |
| + HTTPCacheControl::singleton()->disableCache(true); | |
| $result = $responseException->getResponse(); | |
| } | |
| if(!is_object($result) || $result instanceof SS_HTTPResponse) return $result; | |
| diff --git a/control/FlushRequestFilter.php b/control/FlushRequestFilter.php | |
| index 64d8de6..5a6e295 100644 | |
| --- a/control/FlushRequestFilter.php | |
| +++ b/control/FlushRequestFilter.php | |
| @@ -19,7 +19,7 @@ class FlushRequestFilter implements RequestFilter { | |
| public function postRequest(SS_HTTPRequest $request, SS_HTTPResponse $response, DataModel $model) { | |
| if(array_key_exists('flush', $request->getVars())) { | |
| - HTTPCacheControl::singleton()->disableCaching(); | |
| + HTTPCacheControl::singleton()->disableCache(true); | |
| } | |
| return true; | |
| } | |
| diff --git a/control/HTTP.php b/control/HTTP.php | |
| index b93df19..5df1481 100644 | |
| --- a/control/HTTP.php | |
| +++ b/control/HTTP.php | |
| @@ -341,9 +341,9 @@ class HTTP { | |
| $config = Config::inst()->forClass(__CLASS__); | |
| // if http caching is disabled by config, disable it - used on dev environments due to frequently changing | |
| - // templates and other data | |
| + // templates and other data. will be overridden by forced publicCache() or privateCache() calls | |
| if ($config->get('disable_http_cache')) { | |
| - HTTPCacheControl::singleton()->disableCaching(); | |
| + HTTPCacheControl::singleton()->disableCache(); | |
| } | |
| // Populate $responseHeaders with all the headers that we want to build | |
| @@ -356,7 +356,7 @@ class HTTP { | |
| $requestHeaders = array_change_key_case(apache_request_headers(), CASE_LOWER); | |
| if (array_key_exists('x-requested-with', $requestHeaders) && strtolower($requestHeaders['x-requested-with']) == 'xmlhttprequest') { | |
| - HTTPCacheControl::singleton()->disableCaching(); | |
| + HTTPCacheControl::singleton()->disableCache(true); | |
| } | |
| } | |
| @@ -400,11 +400,12 @@ class HTTP { | |
| // (http://support.microsoft.com/kb/323308) | |
| // Note: this is also fixable by ticking "Do not save encrypted pages to disk" in advanced options. | |
| HTTPCacheControl::singleton() | |
| - ->privateCache() | |
| + ->privateCache(true) | |
| ->removeDirective('no-cache') | |
| ->removeDirective('no-store'); | |
| } | |
| + // TODO: These risk overriding nocache / privatecache calls. Perhaps this should only be applied if caching is unspecified or specified as public | |
| if (!empty($cacheControlHeaders)) { | |
| HTTPCacheControl::singleton()->setDirectivesFromArray($cacheControlHeaders); | |
| } | |
| diff --git a/control/HTTPCacheControl.php b/control/HTTPCacheControl.php | |
| index c538a50..dbfd373 100644 | |
| --- a/control/HTTPCacheControl.php | |
| +++ b/control/HTTPCacheControl.php | |
| @@ -20,11 +20,33 @@ class HTTPCacheControl extends SS_Object { | |
| private $state = array(); | |
| /** | |
| - * Whether the cache-control object is locked to further changes | |
| - * | |
| - * @var bool | |
| + * Forcing level of previous setting; higher number wins | |
| + * Combination of consts belo | |
| + *w | |
| + * @var int | |
| */ | |
| - protected $locked = false; | |
| + protected $forcingLevel = 0; | |
| + | |
| + /** | |
| + * Forcing level forced, optionally combined with one of the below. | |
| + */ | |
| + private const LEVEL_FORCED = 10; | |
| + | |
| + /** | |
| + * Forcing level caching disabled. Overrides public/private. | |
| + */ | |
| + private const LEVEL_DISABLED = 3; | |
| + | |
| + /** | |
| + * Forcing level private-cached. Overrides public. | |
| + */ | |
| + private const LEVEL_PRIVATE = 2; | |
| + | |
| + /** | |
| + * Forcing level public cached. Lowest priority. | |
| + */ | |
| + private const LEVEL_PUBLIC = 1; | |
| + | |
| /** | |
| * A list of allowed cache directives for HTTPResponses | |
| @@ -48,17 +70,6 @@ class HTTPCacheControl extends SS_Object { | |
| ); | |
| /** | |
| - * Lock the current state of the cache control to prevent further modifications | |
| - * | |
| - * @return $this | |
| - */ | |
| - public function lock() | |
| - { | |
| - $this->locked = true; | |
| - return $this; | |
| - } | |
| - | |
| - /** | |
| * Low level method for setting directives include any experimental or custom ones added via config | |
| * | |
| * @param string $directive | |
| @@ -203,35 +214,6 @@ class HTTPCacheControl extends SS_Object { | |
| } | |
| /** | |
| - * Indicates that the response may be cached by any cache. (eg: CDNs, Proxies, Web browsers) | |
| - * | |
| - * Also removes `public` as this is a contradictory directive | |
| - * | |
| - * @return $this | |
| - */ | |
| - public function setPublic() | |
| - { | |
| - $this->setDirective('public'); | |
| - $this->removeDirective('private'); | |
| - return $this; | |
| - } | |
| - | |
| - /** | |
| - * Indicates that the response is intended for a single user and must not be stored by a shared cache. | |
| - * A private cache may store the response. | |
| - * | |
| - * Also removes `private` as this is a contradictory directive | |
| - * | |
| - * @return $this | |
| - */ | |
| - public function setPrivate() | |
| - { | |
| - $this->setDirective('private'); | |
| - $this->removeDirective('public'); | |
| - return $this; | |
| - } | |
| - | |
| - /** | |
| * Specifies the maximum amount of time (seconds) a resource will be considered fresh. | |
| * This directive is relative to the time of the request. | |
| * | |
| @@ -282,44 +264,68 @@ class HTTPCacheControl extends SS_Object { | |
| * Removes all state and replaces it with `no-cache, no-store, must-revalidate`. Although `no-store` is sufficient | |
| * the others are added under recommendation from Mozilla (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#Examples) | |
| * | |
| + * This will take precendence over unforced privateCache / publicCache calls | |
| + * | |
| + * @param bool $force Force the cache to private even if it's forced private or public | |
| * @return $this | |
| */ | |
| - public function disableCaching() | |
| + public function disableCache($force = false) | |
| { | |
| + // Only exeucute this if its forcing level is high enough | |
| + $forcingLevel = self::LEVEL_DISABLED + ($force ? self::LEVEL_FORCED : 0); | |
| + $this->forcingLevel = $forcingLevel; | |
| + | |
| $this->state = array( | |
| 'no-cache' => null, | |
| 'no-store' => null, | |
| 'must-revalidate' => null, | |
| ); | |
| - $this->lock(); | |
| return $this; | |
| } | |
| /** | |
| - * Helper function to set the current cache to private | |
| + * Indicates that the response is intended for a single user and must not be stored by a shared cache. | |
| + * A private cache may store the response. | |
| + * | |
| + * Also removes `private` as this is a contradictory directive | |
| * | |
| + * @param bool $force Force the cache to private even if it's forced public | |
| * @return $this | |
| */ | |
| - public function privateCache() | |
| + public function privateCache($force = false) | |
| { | |
| - $this->setPrivate(); | |
| + // Only exeucute this if its forcing level is high enough | |
| + $forcingLevel = self::LEVEL_PRIVATE + ($force ? self::LEVEL_FORCED : 0); | |
| + if ($forcingLevel < $this->forcingLevel) { | |
| + return; | |
| + } | |
| + $this->forcingLevel = $forcingLevel; | |
| + | |
| + // Update the directives | |
| + $this->setDirective('private'); | |
| + $this->removeDirective('public'); | |
| return $this; | |
| } | |
| /** | |
| - * Helper function to set the current cache to public | |
| + * Indicates that the response may be cached by any cache. (eg: CDNs, Proxies, Web browsers) | |
| * | |
| - * @param bool $force Force the cache to public even if it's private | |
| + * Also removes `public` as this is a contradictory directive | |
| * | |
| + * @param bool $force Force the cache to public even if it's private, unless it's been forced private | |
| * @return $this | |
| */ | |
| public function publicCache($force = false) | |
| { | |
| - if ($force || !$this->hasDirective('private')) { | |
| - $this->setPublic(); | |
| - } else { | |
| - user_error('Cannot change a private cache to public', E_USER_WARNING); | |
| + // Only exeucute this if its forcing level is high enough | |
| + $forcingLevel = self::LEVEL_PUBLIC + ($force ? self::LEVEL_FORCED : 0); | |
| + if ($forcingLevel < $this->forcingLevel) { | |
| + return; | |
| } | |
| + $this->forcingLevel = $forcingLevel; | |
| + | |
| + $this->setDirective('public'); | |
| + $this->removeDirective('private'); | |
| return $this; | |
| } | |
| diff --git a/control/VersionedRequestFilter.php b/control/VersionedRequestFilter.php | |
| index aae5951..7c71de1 100644 | |
| --- a/control/VersionedRequestFilter.php | |
| +++ b/control/VersionedRequestFilter.php | |
| @@ -46,7 +46,7 @@ class VersionedRequestFilter implements RequestFilter { | |
| public function postRequest(SS_HTTPRequest $request, SS_HTTPResponse $response, DataModel $model) { | |
| if (Versioned::current_stage() !== Versioned::LIVE && !HTTPCacheControl::singleton()->hasDirective('no-store')) { | |
| - HTTPCacheControl::singleton()->privateCache(); | |
| + HTTPCacheControl::singleton()->privateCache(true); | |
| } | |
| return true; | |
| } | |
| diff --git a/forms/Form.php b/forms/Form.php | |
| index b07a029..d2f7c00 100644 | |
| --- a/forms/Form.php | |
| +++ b/forms/Form.php | |
| @@ -855,7 +855,7 @@ class Form extends RequestHandler { | |
| // If we need to disable cache, do it | |
| if ($needsCacheDisabled) { | |
| - HTTPCacheControl::singleton()->disableCaching(); | |
| + HTTPCacheControl::singleton()->disableCache(true); | |
| } | |
| $attrs = $this->getAttributes(); | |
| diff --git a/security/Security.php b/security/Security.php | |
| index 5fd36c7..15a9058 100644 | |
| --- a/security/Security.php | |
| +++ b/security/Security.php | |
| @@ -240,7 +240,7 @@ class Security extends Controller implements TemplateGlobalProvider { | |
| if(!$controller) $controller = Controller::curr(); | |
| - HTTPCacheControl::singleton()->disableCaching(); | |
| + HTTPCacheControl::singleton()->disableCache(true); | |
| if(Director::is_ajax()) { | |
| $response = ($controller) ? $controller->getResponse() : new SS_HTTPResponse(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment