-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathCacheKey.php
More file actions
127 lines (105 loc) · 4.05 KB
/
CacheKey.php
File metadata and controls
127 lines (105 loc) · 4.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
<?php
namespace Terraformers\KeysForCache\Models;
use SilverStripe\Core\Validation\ValidationException;
use SilverStripe\ORM\DataObject;
use SilverStripe\Versioned\Versioned;
use Terraformers\KeysForCache\Extensions\CacheKeyExtension;
/**
* Maintain and manage cache keys for records
*
* @property string $RecordClass
* @property int $RecordID
* @property string $KeyHash
* @method DataObject|CacheKeyExtension Record()
* @mixin Versioned
*/
class CacheKey extends DataObject
{
private static string $table_name = 'CacheKey';
private static array $db = [
'KeyHash' => 'Varchar',
];
private static array $has_one = [
'Record' => DataObject::class,
];
private static array $extensions = [
Versioned::class,
];
private static bool $publish_recursive = false;
/**
* Update the CacheKey if it is invalidated,
* Create a CacheKey if it is empty
*/
public static function updateOrCreateKey(DataObject $dataObject): ?CacheKey
{
$cacheKey = static::findOrCreate($dataObject);
if (!$cacheKey) {
return null;
}
$cacheKey->KeyHash = self::generateKeyHash($dataObject);
return $cacheKey;
}
public static function findInStage(DataObject $dataObject): ?CacheKey
{
// The configuration for this DataObject has specified that it does not use CacheKeys
if (!$dataObject->config()->get('has_cache_key')) {
return null;
}
// This search will be performed in whatever your current Stage is
return static::get()->filter([
'RecordClass' => $dataObject->ClassName,
'RecordID' => $dataObject->ID,
])->first();
}
/**
* @param DataObject|CacheKeyExtension $dataObject
* @return CacheKey|null
* @throws ValidationException
*/
public static function findOrCreate(DataObject $dataObject): ?CacheKey
{
// The configuration for this DataObject has specified that it does not use CacheKeys
if (!$dataObject->config()->get('has_cache_key')) {
return null;
}
// We need to ensure that we fetch our CacheKey with our reading mode set to DRAFT. During a publish event, our
// reading mode is LIVE, which would mean that we won't ever find a DRAFT only CacheKey that matches our
// criteria
$cacheKey = Versioned::withVersionedMode(static function () use ($dataObject): ?CacheKey {
Versioned::set_stage(Versioned::DRAFT);
return static::get()->filter([
'RecordClass' => $dataObject->ClassName,
'RecordID' => $dataObject->ID,
])->first();
});
if ($cacheKey === null || !$cacheKey->exists()) {
$cacheKey = static::create();
$cacheKey->RecordClass = $dataObject->ClassName;
$cacheKey->RecordID = $dataObject->ID;
$cacheKey->KeyHash = self::generateKeyHash($dataObject);
}
return $cacheKey;
}
/**
* @param DataObject|CacheKeyExtension $dataObject
*/
public static function remove(DataObject $dataObject): void
{
// There is a non-zero chance that we could have multiple CacheKeys for a single record. If everything always
// worked perfectly then it shouldn't happen, but from a data consistency point of view, it is possible. This
// is our opportunity to clean it up
foreach ($dataObject->CacheKeys() as $cacheKey) {
$cacheKey->doArchive();
}
}
private static function generateKeyHash(DataObject $dataObject): string
{
// getUniqueKey() has only been around since 4.7, but ideally this is what we would like to use as the base for
// our KeyHash
$uniqueKey = $dataObject->hasMethod('getUniqueKey')
? $dataObject->getUniqueKey()
: sprintf('%s-%s', $dataObject->ClassName, $dataObject->ID);
$dataObject->invokeWithExtensions('updateGenerateKeyHash', $uniqueKey);
return implode('-', [$uniqueKey, microtime(true)]);
}
}