CachingPolicy::setCacheAge()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
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
The private property $disable_cache_age_in_dev is not used, and could be removed.
Loading history...
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
Deprecated Code introduced by
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 ignore-deprecated  annotation

147
            $response->addHeader("Last-Modified", /** @scrutinizer ignore-deprecated */ self::gmt_date($timestamp));

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.

Loading history...
148
        }
149
150
        $expires = time() + HTTPCacheControlMiddleware::singleton()->getDirective('max-age');
151
        $response->addHeader("Expires", self::gmt_date($expires));
0 ignored issues
show
Deprecated Code introduced by
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 ignore-deprecated  annotation

151
        $response->addHeader("Expires", /** @scrutinizer ignore-deprecated */ self::gmt_date($expires));

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.

Loading history...
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