Passed
Push — master ( ba9102...299015 )
by Nicolaas
11:04
created

PageControllerExtension::HasCacheKeyHeader()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 3
b 0
f 0
1
<?php
2
3
namespace Sunnysideup\SimpleTemplateCaching\Extensions;
4
5
use PageController;
0 ignored issues
show
Bug introduced by
The type PageController was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
use SilverStripe\Core\Config\Config;
7
use SilverStripe\Core\Extension;
8
use SilverStripe\Security\Security;
9
10
/**
11
 * Class \Sunnysideup\SimpleTemplateCaching\Extensions\PageControllerExtension.
12
 *
13
 * @property PageController|PageControllerExtension $owner
14
 */
15
class PageControllerExtension extends Extension
16
{
17
    private static bool $unique_cache_for_each_member = true;
18
    /**
19
     * make sure to set unique_cache_for_each_member to false
20
     * to use this.
21
     *
22
     * @var boolean
23
     */
24
    private static bool $unique_cache_for_each_member_group_combo = false;
25
    /**
26
     * @var null|string
27
     */
28
    protected static $_cache_key_any_data_object_changes;
29
30
    /**
31
     * @var null|bool
32
     */
33
    private static $_can_cache_content;
34
35
    /**
36
     * @var string
37
     */
38
    private static $_can_cache_content_string = '';
39
40
41
    /**
42
     * does the page have cache keys AKA can it be cached?
43
     */
44
    public function HasCacheKeys(): bool
45
    {
46
        $owner = $this->getOwner();
47
        if (null === self::$_can_cache_content) {
48
            self::$_can_cache_content_string = '';
49
            if ($owner->hasMethod('canCachePage')) {
50
                // if it can cache the page, then it the cache string will remain empty.
51
                self::$_can_cache_content_string .= $owner->canCachePage() ? '' : $this->getRandomKey();
52
            }
53
54
            //action
55
            $action = $owner->request->param('Action');
56
            if ($action) {
57
                self::$_can_cache_content_string .= 'UA'.$action;
58
            }
59
60
            // id
61
            $id = $owner->request->param('ID');
62
            if ($id) {
63
                self::$_can_cache_content_string .= 'UI'.$id;
64
            }
65
66
            // otherid
67
            $otherId = $owner->request->param('OtherID');
68
            if ($otherId) {
69
                self::$_can_cache_content_string .= 'UI'.$otherId;
70
            }
71
72
            //request vars
73
            $requestVars = $owner->request->requestVars();
74
            if ($requestVars) {
75
                foreach ($owner->request->requestVars() as $key => $item) {
76
                    self::$_can_cache_content_string .= serialize($key.$item);
77
                }
78
            }
79
80
            //member
81
            $member = Security::getCurrentUser();
82
            if ($member && $member->exists()) {
83
                if(Config::inst()->get(self::class, 'unique_cache_for_each_member')) {
84
                    self::$_can_cache_content_string .= 'UM'.$member->ID;
85
                } elseif(Config::inst()->get(self::class, 'unique_cache_for_each_member_group_combo')) {
86
                    $groupIds = $member->Groups()->columnUnique();
87
                    sort($groupIds, SORT_NUMERIC);
88
                    self::$_can_cache_content_string .= 'UG'.implode(',', $groupIds);
89
                }
90
            }
91
            // crucial
92
            self::$_can_cache_content = ('' === trim(self::$_can_cache_content_string));
93
        }
94
95
        return self::$_can_cache_content;
96
    }
97
98
    public function HasCacheKeyHeader(): bool
99
    {
100
        return $this->HasCacheKeys();
101
    }
102
103
    public function HasCacheKeyMenu(): bool
104
    {
105
        return $this->HasCacheKeys();
106
    }
107
108
    public function HasCacheKeyContent(): bool
109
    {
110
        if($this->getOwner()->NeverCachePublicly) {
111
            return false;
112
        }
113
        return $this->HasCacheKeys();
114
    }
115
116
    public function HasCacheKeyFooter(): bool
117
    {
118
        return $this->HasCacheKeys();
119
    }
120
121
    public function CacheKeyHeader(?bool $includePageId = false, ?bool $ignoreHasCacheKeys = false): string
122
    {
123
        return $this->CacheKeyGenerator('H', $includePageId, $ignoreHasCacheKeys);
124
    }
125
126
    public function CacheKeyMenu(?bool $includePageId = true, ?bool $ignoreHasCacheKeys = false): string
127
    {
128
        return $this->CacheKeyGenerator('M', $includePageId, $ignoreHasCacheKeys);
129
    }
130
131
    public function CacheKeyFooter(?bool $includePageId = false, ?bool $ignoreHasCacheKeys = false): string
132
    {
133
        return $this->CacheKeyGenerator('F', $includePageId, $ignoreHasCacheKeys);
134
    }
135
136
    public function CacheKeyContent(?bool $ignoreHasCacheKeys = false): string
0 ignored issues
show
Unused Code introduced by
The parameter $ignoreHasCacheKeys is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

136
    public function CacheKeyContent(/** @scrutinizer ignore-unused */ ?bool $ignoreHasCacheKeys = false): string

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
137
    {
138
        $owner = $this->getOwner();
139
        if($owner->NeverCachePublicly) {
140
            return $this->getRandomKey();
141
        }
142
        $cacheKey = $this->CacheKeyGenerator('C');
143
        if ($owner->hasMethod('CacheKeyContentCustom')) {
144
            $cacheKey .= '_' . $owner->CacheKeyContentCustom();
145
        }
146
147
        return $cacheKey;
148
    }
149
150
    public function CacheKeyGenerator(string $letter, ?bool $includePageId = true, ?bool $ignoreHasCacheKeys = false): string
151
    {
152
        $owner = $this->getOwner();
153
        if ($this->HasCacheKeys() || $ignoreHasCacheKeys) {
154
            $string = $letter . '_' . $this->getCanCacheContentString() . '_' . $this->cacheKeyAnyDataObjectChanges();
155
156
            if ($includePageId) {
157
                $string .= '_ID_' . $owner->ID;
158
            }
159
        } else {
160
            $string = 'NOT_CACHED__ID_' .  $this->getRandomKey();
161
        }
162
163
        return $string;
164
    }
165
166
    /**
167
     * if the cache string is NOT empty then we cannot cache
168
     * as there are specific caching values that indicate the page can not be cached.
169
     */
170
    protected function canCacheCheck(): bool
171
    {
172
        // back to source
173
        return $this->HasCacheKeys();
174
    }
175
176
    protected function getRandomKey()
177
    {
178
        $uniqueId = uniqid('', true);
179
180
        // Combine it with some random data
181
        $randomData = bin2hex(random_bytes(16));
182
183
        // Create a SHA-256 hash
184
        return hash('sha256', $uniqueId . $randomData);
185
    }
186
187
    protected function getCanCacheContentString(): string
188
    {
189
        return self::$_can_cache_content_string;
190
    }
191
192
    protected function cacheKeyAnyDataObjectChanges(): string
193
    {
194
        if (null === self::$_cache_key_any_data_object_changes) {
195
            self::$_cache_key_any_data_object_changes = SimpleTemplateCachingSiteConfigExtension::site_cache_key();
196
        }
197
198
        return self::$_cache_key_any_data_object_changes;
199
    }
200
}
201