55namespace staabm \PHPStanDba \QueryReflection ;
66
77use const LOCK_EX ;
8+ use PHPStan \ShouldNotHappenException ;
89use PHPStan \Type \Type ;
910use staabm \PHPStanDba \DbaException ;
1011use staabm \PHPStanDba \Error ;
1112
1213final class ReflectionCache
1314{
14- public const SCHEMA_VERSION = 'v3-rename-props ' ;
15+ public const SCHEMA_VERSION = 'v4-runtime-config ' ;
1516
1617 /**
1718 * @var string
@@ -28,6 +29,11 @@ final class ReflectionCache
2829 */
2930 private $ changes = [];
3031
32+ /**
33+ * @var bool
34+ */
35+ private $ initialized = false ;
36+
3137 /**
3238 * @var resource
3339 */
@@ -55,19 +61,40 @@ public static function create(string $cacheFile): self
5561 return new self ($ cacheFile );
5662 }
5763
64+ /**
65+ * @deprecated use create() instead
66+ */
5867 public static function load (string $ cacheFile ): self
5968 {
60- $ reflectionCache = new self ($ cacheFile );
61- $ cachedRecords = $ reflectionCache ->readCache (true );
62- if (null !== $ cachedRecords ) {
63- $ reflectionCache ->records = $ cachedRecords ;
69+ return new self ($ cacheFile );
70+ }
71+
72+ /**
73+ * @return array<string, array{error?: ?Error, result?: array<QueryReflector::FETCH_TYPE*, ?Type>}>
74+ */
75+ private function lazyReadRecords ()
76+ {
77+ if ($ this ->initialized ) {
78+ return $ this ->records ;
79+ }
80+
81+ $ cache = $ this ->readCache (true );
82+ if (null !== $ cache ) {
83+ $ this ->records = $ cache ['records ' ];
84+ } else {
85+ $ this ->records = [];
6486 }
87+ $ this ->initialized = true ;
6588
66- return $ reflectionCache ;
89+ return $ this -> records ;
6790 }
6891
6992 /**
70- * @return array<string, array{error?: ?Error, result?: array<QueryReflector::FETCH_TYPE*, ?Type>}>|null
93+ * @return array{
94+ * records: array<string, array{error?: ?Error, result?: array<QueryReflector::FETCH_TYPE*, ?Type>}>,
95+ * runtimeConfig: array<string, scalar>,
96+ * schemaVersion: string
97+ * }|null
7198 */
7299 private function readCache (bool $ useReadLock ): ?array
73100 {
@@ -88,11 +115,20 @@ private function readCache(bool $useReadLock): ?array
88115 }
89116 }
90117
91- if (\is_array ($ cache ) && \array_key_exists ('schemaVersion ' , $ cache ) && self ::SCHEMA_VERSION === $ cache ['schemaVersion ' ]) {
92- return $ cache ['records ' ];
118+ if (!\is_array ($ cache ) || !\array_key_exists ('schemaVersion ' , $ cache ) || self ::SCHEMA_VERSION !== $ cache ['schemaVersion ' ]) {
119+ return null ;
120+ }
121+
122+ if ($ cache ['runtimeConfig ' ] !== QueryReflection::getRuntimeConfiguration ()->toArray ()) {
123+ return null ;
93124 }
94125
95- return null ;
126+ if (!\is_array ($ cache ['records ' ])) {
127+ throw new ShouldNotHappenException ();
128+ }
129+
130+ // @phpstan-ignore-next-line
131+ return $ cache ;
96132 }
97133
98134 public function persist (): void
@@ -122,6 +158,7 @@ public function persist(): void
122158 $ cacheContent = '<?php return ' .var_export ([
123159 'schemaVersion ' => self ::SCHEMA_VERSION ,
124160 'records ' => $ newRecords ,
161+ 'runtimeConfig ' => QueryReflection::getRuntimeConfiguration ()->toArray (),
125162 ], true ).'; ' ;
126163
127164 if (false === file_put_contents ($ this ->cacheFile , $ cacheContent )) {
@@ -139,7 +176,9 @@ public function persist(): void
139176
140177 public function hasValidationError (string $ queryString ): bool
141178 {
142- if (!\array_key_exists ($ queryString , $ this ->records )) {
179+ $ records = $ this ->lazyReadRecords ();
180+
181+ if (!\array_key_exists ($ queryString , $ records )) {
143182 return false ;
144183 }
145184
@@ -150,7 +189,9 @@ public function hasValidationError(string $queryString): bool
150189
151190 public function getValidationError (string $ queryString ): ?Error
152191 {
153- if (!\array_key_exists ($ queryString , $ this ->records )) {
192+ $ records = $ this ->lazyReadRecords ();
193+
194+ if (!\array_key_exists ($ queryString , $ records )) {
154195 throw new DbaException (sprintf ('Cache not populated for query "%s" ' , $ queryString ));
155196 }
156197
@@ -164,7 +205,9 @@ public function getValidationError(string $queryString): ?Error
164205
165206 public function putValidationError (string $ queryString , ?Error $ error ): void
166207 {
167- if (!\array_key_exists ($ queryString , $ this ->records )) {
208+ $ records = $ this ->lazyReadRecords ();
209+
210+ if (!\array_key_exists ($ queryString , $ records )) {
168211 $ this ->changes [$ queryString ] = $ this ->records [$ queryString ] = [];
169212 }
170213
@@ -178,7 +221,9 @@ public function putValidationError(string $queryString, ?Error $error): void
178221 */
179222 public function hasResultType (string $ queryString , int $ fetchType ): bool
180223 {
181- if (!\array_key_exists ($ queryString , $ this ->records )) {
224+ $ records = $ this ->lazyReadRecords ();
225+
226+ if (!\array_key_exists ($ queryString , $ records )) {
182227 return false ;
183228 }
184229
@@ -195,7 +240,9 @@ public function hasResultType(string $queryString, int $fetchType): bool
195240 */
196241 public function getResultType (string $ queryString , int $ fetchType ): ?Type
197242 {
198- if (!\array_key_exists ($ queryString , $ this ->records )) {
243+ $ records = $ this ->lazyReadRecords ();
244+
245+ if (!\array_key_exists ($ queryString , $ records )) {
199246 throw new DbaException (sprintf ('Cache not populated for query "%s" ' , $ queryString ));
200247 }
201248
@@ -216,7 +263,9 @@ public function getResultType(string $queryString, int $fetchType): ?Type
216263 */
217264 public function putResultType (string $ queryString , int $ fetchType , ?Type $ resultType ): void
218265 {
219- if (!\array_key_exists ($ queryString , $ this ->records )) {
266+ $ records = $ this ->lazyReadRecords ();
267+
268+ if (!\array_key_exists ($ queryString , $ records )) {
220269 $ this ->changes [$ queryString ] = $ this ->records [$ queryString ] = [];
221270 }
222271
0 commit comments