@@ -31,6 +31,7 @@ class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
3131 private $ namespace ;
3232 private $ namespaceLen ;
3333 private $ createCacheItem ;
34+ private $ setInnerItem ;
3435 private $ poolHash ;
3536
3637 public function __construct (CacheItemPoolInterface $ pool , string $ namespace = '' , int $ defaultLifetime = 0 )
@@ -43,32 +44,66 @@ public function __construct(CacheItemPoolInterface $pool, string $namespace = ''
4344 function ($ key , $ innerItem ) use ($ defaultLifetime , $ poolHash ) {
4445 $ item = new CacheItem ();
4546 $ item ->key = $ key ;
46- $ item ->value = $ innerItem ->get ();
47+ $ item ->value = $ v = $ innerItem ->get ();
4748 $ item ->isHit = $ innerItem ->isHit ();
4849 $ item ->defaultLifetime = $ defaultLifetime ;
4950 $ item ->innerItem = $ innerItem ;
5051 $ item ->poolHash = $ poolHash ;
52+ // Detect wrapped values that encode for their expiry and creation duration
53+ // For compactness, these values are packed in the key of an array using
54+ // magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F
55+ if (\is_array ($ v ) && 1 === \count ($ v ) && 10 === \strlen ($ k = \key ($ v )) && "\x9D" === $ k [0 ] && "\0" === $ k [5 ] && "\x5F" === $ k [9 ]) {
56+ $ item ->value = $ v [$ k ];
57+ $ v = \unpack ('Ve/Nc ' , \substr ($ k , 1 , -1 ));
58+ $ item ->metadata [CacheItem::METADATA_EXPIRY ] = $ v ['e ' ] + CacheItem::METADATA_EXPIRY_OFFSET ;
59+ $ item ->metadata [CacheItem::METADATA_CTIME ] = $ v ['c ' ];
60+ } elseif ($ innerItem instanceof CacheItem) {
61+ $ item ->metadata = $ innerItem ->metadata ;
62+ }
5163 $ innerItem ->set (null );
5264
5365 return $ item ;
5466 },
5567 null ,
5668 CacheItem::class
5769 );
70+ $ this ->setInnerItem = \Closure::bind (
71+ /**
72+ * @param array $item A CacheItem cast to (array); accessing protected properties requires adding the \0*\0" PHP prefix
73+ */
74+ function (CacheItemInterface $ innerItem , array $ item ) {
75+ // Tags are stored separately, no need to account for them when considering this item's newly set metadata
76+ if (isset (($ metadata = $ item ["\0* \0newMetadata " ])[CacheItem::METADATA_TAGS ])) {
77+ unset($ metadata [CacheItem::METADATA_TAGS ]);
78+ }
79+ if ($ metadata ) {
80+ // For compactness, expiry and creation duration are packed in the key of a array, using magic numbers as separators
81+ $ item ["\0* \0value " ] = array ("\x9D" .pack ('VN ' , (int ) $ metadata [CacheItem::METADATA_EXPIRY ] - CacheItem::METADATA_EXPIRY_OFFSET , $ metadata [CacheItem::METADATA_CTIME ])."\x5F" => $ item ["\0* \0value " ]);
82+ }
83+ $ innerItem ->set ($ item ["\0* \0value " ]);
84+ $ innerItem ->expiresAt (null !== $ item ["\0* \0expiry " ] ? \DateTime::createFromFormat ('U ' , $ item ["\0* \0expiry " ]) : null );
85+ },
86+ null ,
87+ CacheItem::class
88+ );
5889 }
5990
6091 /**
6192 * {@inheritdoc}
6293 */
63- public function get (string $ key , callable $ callback )
94+ public function get (string $ key , callable $ callback, float $ beta = null )
6495 {
6596 if (!$ this ->pool instanceof CacheInterface) {
66- return $ this ->doGet ($ this -> pool , $ key , $ callback );
97+ return $ this ->doGet ($ this , $ key , $ callback, $ beta ?? 1.0 );
6798 }
6899
69100 return $ this ->pool ->get ($ this ->getId ($ key ), function ($ innerItem ) use ($ key , $ callback ) {
70- return $ callback (($ this ->createCacheItem )($ key , $ innerItem ));
71- });
101+ $ item = ($ this ->createCacheItem )($ key , $ innerItem );
102+ $ item ->set ($ value = $ callback ($ item ));
103+ ($ this ->setInnerItem )($ innerItem , (array ) $ item );
104+
105+ return $ value ;
106+ }, $ beta );
72107 }
73108
74109 /**
@@ -164,13 +199,11 @@ private function doSave(CacheItemInterface $item, $method)
164199 return false ;
165200 }
166201 $ item = (array ) $ item ;
167- $ expiry = $ item ["\0* \0expiry " ];
168- if (null === $ expiry && 0 < $ item ["\0* \0defaultLifetime " ]) {
169- $ expiry = time () + $ item ["\0* \0defaultLifetime " ];
202+ if (null === $ item ["\0* \0expiry " ] && 0 < $ item ["\0* \0defaultLifetime " ]) {
203+ $ item ["\0* \0expiry " ] = time () + $ item ["\0* \0defaultLifetime " ];
170204 }
171205 $ innerItem = $ item ["\0* \0poolHash " ] === $ this ->poolHash ? $ item ["\0* \0innerItem " ] : $ this ->pool ->getItem ($ this ->namespace .$ item ["\0* \0key " ]);
172- $ innerItem ->set ($ item ["\0* \0value " ]);
173- $ innerItem ->expiresAt (null !== $ expiry ? \DateTime::createFromFormat ('U ' , $ expiry ) : null );
206+ ($ this ->setInnerItem )($ innerItem , $ item );
174207
175208 return $ this ->pool ->$ method ($ innerItem );
176209 }
0 commit comments