14
14
use Psr \Log \LoggerAwareInterface ;
15
15
use Symfony \Component \Cache \CacheItem ;
16
16
use Symfony \Component \Cache \Exception \InvalidArgumentException ;
17
+ use Symfony \Component \Cache \Marshaller \MarshallerInterface ;
17
18
use Symfony \Component \Cache \ResettableInterface ;
18
19
use Symfony \Component \Cache \Traits \AbstractAdapterTrait ;
19
20
use Symfony \Component \Cache \Traits \ContractsTrait ;
@@ -37,14 +38,17 @@ abstract class AbstractTagAwareAdapter implements TagAwareAdapterInterface, TagA
37
38
38
39
private const TAGS_PREFIX = "\0tags \0" ;
39
40
40
- protected function __construct (string $ namespace = '' , int $ defaultLifetime = 0 )
41
+ private $ marshaller ;
42
+
43
+ protected function __construct (string $ namespace = '' , int $ defaultLifetime = 0 , MarshallerInterface $ marshaller = null )
41
44
{
45
+ $ this ->marshaller = $ marshaller ;
42
46
$ this ->namespace = '' === $ namespace ? '' : CacheItem::validateKey ($ namespace ).': ' ;
43
47
if (null !== $ this ->maxIdLength && \strlen ($ namespace ) > $ this ->maxIdLength - 24 ) {
44
48
throw new InvalidArgumentException (sprintf ('Namespace must be %d chars max, %d given ("%s") ' , $ this ->maxIdLength - 24 , \strlen ($ namespace ), $ namespace ));
45
49
}
46
50
$ this ->createCacheItem = \Closure::bind (
47
- static function ($ key , $ value , $ isHit ) use ($ defaultLifetime ) {
51
+ static function ($ key , $ value , $ isHit ) use ($ defaultLifetime, $ marshaller ) {
48
52
$ item = new CacheItem ();
49
53
$ item ->key = $ key ;
50
54
$ item ->defaultLifetime = $ defaultLifetime ;
@@ -53,6 +57,10 @@ static function ($key, $value, $isHit) use ($defaultLifetime) {
53
57
if (!\is_array ($ value ) || !\array_key_exists ('value ' , $ value )) {
54
58
return $ item ;
55
59
}
60
+ if ($ marshaller && \is_string ($ value ['tags ' ] ?? null )) {
61
+ $ value ['value ' ] = $ marshaller ->unmarshall ($ value ['value ' ]);
62
+ $ value ['tags ' ] = $ marshaller ->unmarshall ($ value ['tags ' ]);
63
+ }
56
64
$ item ->isHit = $ isHit ;
57
65
// Extract value, tags and meta data from the cache value
58
66
$ item ->value = $ value ['value ' ];
@@ -72,7 +80,7 @@ static function ($key, $value, $isHit) use ($defaultLifetime) {
72
80
$ getId = \Closure::fromCallable ([$ this , 'getId ' ]);
73
81
$ tagPrefix = self ::TAGS_PREFIX ;
74
82
$ this ->mergeByLifetime = \Closure::bind (
75
- static function ($ deferred , &$ expiredIds ) use ($ getId , $ tagPrefix ) {
83
+ static function ($ deferred , &$ expiredIds ) use ($ getId , $ tagPrefix, $ marshaller ) {
76
84
$ byLifetime = [];
77
85
$ now = microtime (true );
78
86
$ expiredIds = [];
@@ -93,6 +101,16 @@ static function ($deferred, &$expiredIds) use ($getId, $tagPrefix) {
93
101
$ value = ['value ' => $ item ->value , 'tags ' => []];
94
102
}
95
103
104
+ $ newTags = $ value ['tags ' ];
105
+
106
+ if ($ marshaller ) {
107
+ $ value = $ marshaller ->marshall ($ value , $ failed );
108
+
109
+ if ($ failed ) {
110
+ $ value ['fail ' ] = $ item ->value ;
111
+ }
112
+ }
113
+
96
114
if ($ metadata ) {
97
115
// For compactness, expiry and creation duration are packed, using magic numbers as separators
98
116
$ value ['meta ' ] = pack ('VN ' , (int ) (0.1 + $ metadata [self ::METADATA_EXPIRY ] - self ::METADATA_EXPIRY_OFFSET ), $ metadata [self ::METADATA_CTIME ]);
@@ -101,10 +119,10 @@ static function ($deferred, &$expiredIds) use ($getId, $tagPrefix) {
101
119
// Extract tag changes, these should be removed from values in doSave()
102
120
$ value ['tag-operations ' ] = ['add ' => [], 'remove ' => []];
103
121
$ oldTags = $ item ->metadata [CacheItem::METADATA_TAGS ] ?? [];
104
- foreach (array_diff ($ value [ ' tags ' ] , $ oldTags ) as $ addedTag ) {
122
+ foreach (array_diff ($ newTags , $ oldTags ) as $ addedTag ) {
105
123
$ value ['tag-operations ' ]['add ' ][] = $ getId ($ tagPrefix .$ addedTag );
106
124
}
107
- foreach (array_diff ($ oldTags , $ value [ ' tags ' ] ) as $ removedTag ) {
125
+ foreach (array_diff ($ oldTags , $ newTags ) as $ removedTag ) {
108
126
$ value ['tag-operations ' ]['remove ' ][] = $ getId ($ tagPrefix .$ removedTag );
109
127
}
110
128
@@ -149,6 +167,17 @@ abstract protected function doDelete(array $ids, array $tagData = []): bool;
149
167
*/
150
168
abstract protected function doInvalidate (array $ tagIds ): bool ;
151
169
170
+ protected function doFetchTags (array $ ids ): iterable
171
+ {
172
+ foreach ($ this ->doFetch ($ ids ) as $ id => $ value ) {
173
+ if ($ this ->marshaller && \is_string ($ value ['tags ' ] ?? null )) {
174
+ $ value ['tags ' ] = $ this ->marshaller ->unmarshall ($ value ['tags ' ]);
175
+ }
176
+
177
+ yield $ id => $ value ['tags ' ] ?? [];
178
+ }
179
+ }
180
+
152
181
/**
153
182
* {@inheritdoc}
154
183
*
@@ -232,8 +261,8 @@ public function deleteItems(array $keys)
232
261
unset($ this ->deferred [$ key ]);
233
262
}
234
263
235
- foreach ($ this ->doFetch ($ ids ) as $ id => $ value ) {
236
- foreach ($ value [ ' tags ' ] ?? [] as $ tag ) {
264
+ foreach ($ this ->doFetchTags ($ ids ) as $ id => $ tags ) {
265
+ foreach ($ tags as $ tag ) {
237
266
$ tagData [$ this ->getId (self ::TAGS_PREFIX .$ tag )][] = $ id ;
238
267
}
239
268
}
0 commit comments