1 | <?php |
||||
2 | |||||
3 | namespace SilverStripe\ControllerPolicy\Policies; |
||||
4 | |||||
5 | use SilverStripe\Control\Director; |
||||
6 | use SilverStripe\Control\HTTP; |
||||
7 | use SilverStripe\Control\HTTPRequest; |
||||
8 | use SilverStripe\Control\HTTPResponse; |
||||
9 | use SilverStripe\Control\Middleware\HTTPCacheControlMiddleware; |
||||
10 | use SilverStripe\ControllerPolicy\ControllerPolicy; |
||||
11 | |||||
12 | /** |
||||
13 | * A rewrite of the default SilverStripe behaviour allowing more customisation. Consuming code can provide its own |
||||
14 | * callbacks for providing custom cacheAge, vary and timestamp parameters. |
||||
15 | * |
||||
16 | * See PageControlledPolicy as an example implementation of such customisation that applies on top of default. |
||||
17 | * |
||||
18 | * Extends HTTP to get access to globals describing the Last-Modified and Etag data. |
||||
19 | */ |
||||
20 | |||||
21 | class CachingPolicy extends HTTP implements ControllerPolicy |
||||
22 | { |
||||
23 | /** |
||||
24 | * Whether to disable the cache age (set to zero) in dev environments |
||||
25 | * |
||||
26 | * @config |
||||
27 | * @var bool |
||||
28 | */ |
||||
29 | private static $disable_cache_age_in_dev = true; |
||||
0 ignored issues
–
show
introduced
by
![]() |
|||||
30 | |||||
31 | /** |
||||
32 | * Max-age seconds to cache for if configuration not available from the originator. |
||||
33 | * |
||||
34 | * @var int |
||||
35 | */ |
||||
36 | protected $cacheAge = 0; |
||||
37 | |||||
38 | /** |
||||
39 | * Vary string to add if configuration is not available from the originator. |
||||
40 | * |
||||
41 | * Note on vary headers: Do not add user-agent unless you vary on it AND you have configured user-agent |
||||
42 | * clustering in some way, otherwise this will be an equivalent to disabling caching as there |
||||
43 | * is a lot of different UAs in the wild. |
||||
44 | * |
||||
45 | * @var string |
||||
46 | */ |
||||
47 | protected $vary = ''; |
||||
48 | |||||
49 | /** |
||||
50 | * Set the cache age |
||||
51 | * |
||||
52 | * @param int $cacheAge |
||||
53 | * @return $this |
||||
54 | */ |
||||
55 | public function setCacheAge($cacheAge) |
||||
56 | { |
||||
57 | $this->cacheAge = $cacheAge; |
||||
58 | return $this; |
||||
59 | } |
||||
60 | |||||
61 | /** |
||||
62 | * Get the cache age |
||||
63 | * |
||||
64 | * @return int |
||||
65 | */ |
||||
66 | public function getCacheAge() |
||||
67 | { |
||||
68 | return $this->cacheAge; |
||||
69 | } |
||||
70 | |||||
71 | /** |
||||
72 | * Set the "vary" content header |
||||
73 | * |
||||
74 | * @param string $vary |
||||
75 | * @return $this |
||||
76 | */ |
||||
77 | public function setVary($vary) |
||||
78 | { |
||||
79 | $this->vary = $vary; |
||||
80 | return $this; |
||||
81 | } |
||||
82 | |||||
83 | /** |
||||
84 | * Get the "vary" content header |
||||
85 | * |
||||
86 | * @return string |
||||
87 | */ |
||||
88 | public function getVary() |
||||
89 | { |
||||
90 | return $this->vary; |
||||
91 | } |
||||
92 | |||||
93 | /** |
||||
94 | * @see HTTP::add_cache_headers() |
||||
95 | * |
||||
96 | * @param object $originator |
||||
97 | * @param HTTPRequest $request |
||||
98 | * @param HTTPResponse $response |
||||
99 | */ |
||||
100 | public function applyToResponse($originator, HTTPRequest $request, HTTPResponse $response) |
||||
101 | { |
||||
102 | $cacheAge = $this->getCacheAge(); |
||||
103 | $vary = $this->getVary(); |
||||
104 | |||||
105 | // Allow overriding max-age from the object hooked up to the policed controller. |
||||
106 | if ($originator->hasMethod('getCacheAge')) { |
||||
107 | $extendedCacheAge = $originator->getCacheAge($cacheAge); |
||||
108 | if ($extendedCacheAge !== null) { |
||||
109 | $cacheAge = $extendedCacheAge; |
||||
110 | } |
||||
111 | } |
||||
112 | |||||
113 | // Development sites have frequently changing templates; this can get stuffed up by the code |
||||
114 | // below. |
||||
115 | if (Director::isDev() && $this->config()->get('disable_cache_age_in_dev')) { |
||||
116 | $cacheAge = 0; |
||||
117 | } |
||||
118 | |||||
119 | // Same for vary, but probably less useful. |
||||
120 | if ($originator->hasMethod('getVary')) { |
||||
121 | $extendedVary = $originator->getVary($vary); |
||||
122 | if ($extendedVary !== null) { |
||||
123 | $vary = $extendedVary; |
||||
124 | } |
||||
125 | } |
||||
126 | |||||
127 | // Enable caching via core APIs |
||||
128 | HTTPCacheControlMiddleware::singleton()->enableCache(); |
||||
129 | |||||
130 | if ($cacheAge > 0) { |
||||
131 | HTTPCacheControlMiddleware::singleton()->setMaxAge($cacheAge); |
||||
132 | } |
||||
133 | |||||
134 | // Merge vary into response |
||||
135 | if ($vary) { |
||||
136 | HTTPCacheControlMiddleware::singleton()->addVary($vary); |
||||
137 | } |
||||
138 | |||||
139 | // Find out when the URI was last modified. Allows customisation, but fall back HTTP timestamp collector. |
||||
140 | if ($originator->hasMethod('getModificationTimestamp')) { |
||||
141 | $timestamp = $originator->getModificationTimestamp(); |
||||
142 | } else { |
||||
143 | $timestamp = HTTP::$modification_date; |
||||
144 | } |
||||
145 | |||||
146 | if ($timestamp) { |
||||
147 | $response->addHeader("Last-Modified", self::gmt_date($timestamp)); |
||||
0 ignored issues
–
show
The function
SilverStripe\Control\HTTP::gmt_date() has been deprecated: 4.2.0:5.0.0 Inline if you need this
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
148 | } |
||||
149 | |||||
150 | $expires = time() + HTTPCacheControlMiddleware::singleton()->getDirective('max-age'); |
||||
151 | $response->addHeader("Expires", self::gmt_date($expires)); |
||||
0 ignored issues
–
show
The function
SilverStripe\Control\HTTP::gmt_date() has been deprecated: 4.2.0:5.0.0 Inline if you need this
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
152 | |||||
153 | // Now that we've generated them, either output them or attach them to the SS_HTTPResponse as appropriate |
||||
154 | HTTPCacheControlMiddleware::singleton()->applyToResponse($response); |
||||
155 | } |
||||
156 | } |
||||
157 |