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 , MarshallerInterface $ marshaller )
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 (\is_string ($ value ['tags ' ] ?? null )) {
61
+ $ value ['value ' ] = $ marshaller ->unmarshall ($ value ['value ' ]);
62
+ $ value ['tags ' ] = '' === $ 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,17 @@ static function ($deferred, &$expiredIds) use ($getId, $tagPrefix) {
93
101
$ value = ['value ' => $ item ->value , 'tags ' => []];
94
102
}
95
103
104
+ $ newTags = $ value ['tags ' ];
105
+ $ value = $ marshaller ->marshall ($ value , $ failed );
106
+
107
+ if ([] === $ newTags ) {
108
+ $ value ['tags ' ] = '' ;
109
+ }
110
+
111
+ if ($ failed ) {
112
+ $ value ['fail ' ] = $ item ->value ;
113
+ }
114
+
96
115
if ($ metadata ) {
97
116
// For compactness, expiry and creation duration are packed, using magic numbers as separators
98
117
$ value ['meta ' ] = pack ('VN ' , (int ) (0.1 + $ metadata [self ::METADATA_EXPIRY ] - self ::METADATA_EXPIRY_OFFSET ), $ metadata [self ::METADATA_CTIME ]);
@@ -101,10 +120,10 @@ static function ($deferred, &$expiredIds) use ($getId, $tagPrefix) {
101
120
// Extract tag changes, these should be removed from values in doSave()
102
121
$ value ['tag-operations ' ] = ['add ' => [], 'remove ' => []];
103
122
$ oldTags = $ item ->metadata [CacheItem::METADATA_TAGS ] ?? [];
104
- foreach (array_diff ($ value [ ' tags ' ] , $ oldTags ) as $ addedTag ) {
123
+ foreach (array_diff ($ newTags , $ oldTags ) as $ addedTag ) {
105
124
$ value ['tag-operations ' ]['add ' ][] = $ getId ($ tagPrefix .$ addedTag );
106
125
}
107
- foreach (array_diff ($ oldTags , $ value [ ' tags ' ] ) as $ removedTag ) {
126
+ foreach (array_diff ($ oldTags , $ newTags ) as $ removedTag ) {
108
127
$ value ['tag-operations ' ]['remove ' ][] = $ getId ($ tagPrefix .$ removedTag );
109
128
}
110
129
@@ -149,6 +168,20 @@ abstract protected function doDelete(array $ids, array $tagData = []): bool;
149
168
*/
150
169
abstract protected function doInvalidate (array $ tagIds ): bool ;
151
170
171
+ /**
172
+ * Returns the tags bound to the provided ids.
173
+ */
174
+ protected function doFetchTags (array $ ids ): iterable
175
+ {
176
+ foreach ($ this ->doFetch ($ ids ) as $ id => $ value ) {
177
+ if (\is_string ($ value ['tags ' ] ?? null )) {
178
+ $ value ['tags ' ] = '' === $ value ['tags ' ] ? [] : $ this ->marshaller ->unmarshall ($ value ['tags ' ]);
179
+ }
180
+
181
+ yield $ id => $ value ['tags ' ] ?? [];
182
+ }
183
+ }
184
+
152
185
/**
153
186
* {@inheritdoc}
154
187
*
@@ -233,8 +266,8 @@ public function deleteItems(array $keys)
233
266
}
234
267
235
268
try {
236
- foreach ($ this ->doFetch ($ ids ) as $ id => $ value ) {
237
- foreach ($ value [ ' tags ' ] ?? [] as $ tag ) {
269
+ foreach ($ this ->doFetchTags ($ ids ) as $ id => $ tags ) {
270
+ foreach ($ tags as $ tag ) {
238
271
$ tagData [$ this ->getId (self ::TAGS_PREFIX .$ tag )][] = $ id ;
239
272
}
240
273
}
0 commit comments