44
55namespace TypePHP \Validator ;
66
7+ use PHPStan \PhpDocParser \Ast \ConstExpr \ConstExprIntegerNode ;
8+ use PHPStan \PhpDocParser \Ast \ConstExpr \ConstExprStringNode ;
79use PHPStan \PhpDocParser \Ast \ConstExpr \ConstFetchNode ;
810use PHPStan \PhpDocParser \Ast \Type \ArrayShapeNode ;
9- use PHPStan \PhpDocParser \Ast \ConstExpr \ConstExprStringNode ;
10- use PHPStan \PhpDocParser \Ast \ConstExpr \ConstExprIntegerNode ;
1111use PHPStan \PhpDocParser \Ast \Type \ConstTypeNode ;
1212use PHPStan \PhpDocParser \Ast \Type \GenericTypeNode ;
1313use PHPStan \PhpDocParser \Ast \Type \IdentifierTypeNode ;
@@ -29,7 +29,7 @@ final class GenericValidator implements TypeValidatorInterface
2929 private static array $ constantCache = [];
3030
3131 /**
32- * @var array<string, array<int, string>>
32+ * @var array<string, array<int, string>>
3333 */
3434 private static array $ enumKeyCache = [];
3535
@@ -78,7 +78,7 @@ private function validateKeyOf(mixed $value, GenericTypeNode $node, string $cont
7878 $ constName = $ constExpr ->name ;
7979 $ cacheKey = $ fqcn !== '' ? "$ fqcn:: $ constName " : $ constName ;
8080
81- if (!\array_key_exists ($ cacheKey , self ::$ constantCache )) {
81+ if (! \array_key_exists ($ cacheKey , self ::$ constantCache )) {
8282 $ constValue = false ;
8383 if ($ fqcn !== '' ) {
8484 if (class_exists ($ fqcn ) || interface_exists ($ fqcn )) {
@@ -101,21 +101,23 @@ private function validateKeyOf(mixed $value, GenericTypeNode $node, string $cont
101101 $ constValue = self ::$ constantCache [$ cacheKey ];
102102
103103 if (\is_array ($ constValue )) {
104- if ((!\is_int ($ value ) && !\is_string ($ value )) || !\array_key_exists ($ value , $ constValue )) {
104+ if ((! \is_int ($ value ) && ! \is_string ($ value )) || ! \array_key_exists ($ value , $ constValue )) {
105105 return ErrorFactory::createError ($ context . " must be a key of $ cacheKey, " . TypeFormatter::formatGivenValue ($ value ) . ' given ' );
106106 }
107+
107108 return null ;
108109 }
109110 } elseif ($ targetType instanceof IdentifierTypeNode) {
110111 $ enumClass = $ targetType ->name ;
111112 if (ClassNameValidator::isValid ($ enumClass ) && enum_exists ($ enumClass )) {
112- if (!isset (self ::$ enumKeyCache [$ enumClass ])) {
113- self ::$ enumKeyCache [$ enumClass ] = array_map (fn ($ case ) => $ case ->name , $ enumClass ::cases ());
113+ if (! isset (self ::$ enumKeyCache [$ enumClass ])) {
114+ self ::$ enumKeyCache [$ enumClass ] = array_map (fn ($ case ) => $ case ->name , $ enumClass ::cases ());
114115 }
115116
116- if (!\in_array ($ value , self ::$ enumKeyCache [$ enumClass ], true )) {
117+ if (! \in_array ($ value , self ::$ enumKeyCache [$ enumClass ], true )) {
117118 return ErrorFactory::createError ($ context . " must be a key of enum $ enumClass, " . TypeFormatter::formatGivenValue ($ value ) . ' given ' );
118119 }
120+
119121 return null ;
120122 }
121123 } elseif ($ targetType instanceof ArrayShapeNode) {
@@ -130,9 +132,10 @@ private function validateKeyOf(mixed $value, GenericTypeNode $node, string $cont
130132 }
131133 }
132134
133- if (!\in_array ($ value , $ validKeys , true )) {
135+ if (! \in_array ($ value , $ validKeys , true )) {
134136 return ErrorFactory::createError ($ context . ' must be a key of the specified array shape, ' . TypeFormatter::formatGivenValue ($ value ) . ' given ' );
135137 }
138+
136139 return null ;
137140 }
138141
@@ -146,7 +149,7 @@ private function validateKeyOf(mixed $value, GenericTypeNode $node, string $cont
146149 * 1. Array Constants: If T is a class constant (e.g., self::DRIVER_MAP), it safely reflects the
147150 * target class to bypass visibility restrictions (private/protected), caches the array in memory,
148151 * and verifies that the provided value exists as a value in that array.
149- * 2. Enums: If T is a Backed Enum identifier, it extracts and caches the enum case backing values,
152+ * 2. Enums: If T is a Backed Enum identifier, it extracts and caches the enum case backing values,
150153 * then verifies that the provided value matches a valid case value.
151154 * 3. Fallback: Returns null gracefully for unresolvable or unsupported structures.
152155 */
@@ -160,7 +163,7 @@ private function validateValueOf(mixed $value, GenericTypeNode $node, string $co
160163 $ constName = $ constExpr ->name ;
161164 $ cacheKey = $ fqcn !== '' ? "$ fqcn:: $ constName " : $ constName ;
162165
163- if (!\array_key_exists ($ cacheKey , self ::$ constantCache )) {
166+ if (! \array_key_exists ($ cacheKey , self ::$ constantCache )) {
164167 $ constValue = false ;
165168 if ($ fqcn !== '' ) {
166169 if (class_exists ($ fqcn ) || interface_exists ($ fqcn )) {
@@ -183,27 +186,30 @@ private function validateValueOf(mixed $value, GenericTypeNode $node, string $co
183186 $ constValue = self ::$ constantCache [$ cacheKey ];
184187
185188 if (\is_array ($ constValue )) {
186- if (!\in_array ($ value , $ constValue , true )) {
189+ if (! \in_array ($ value , $ constValue , true )) {
187190 return ErrorFactory::createError ($ context . " must be a value of $ cacheKey, " . TypeFormatter::formatGivenValue ($ value ) . ' given ' );
188191 }
192+
189193 return null ;
190194 }
191195 } elseif ($ targetType instanceof IdentifierTypeNode) {
192196 $ enumClass = $ targetType ->name ;
193197 if (ClassNameValidator::isValid ($ enumClass ) && enum_exists ($ enumClass ) && is_subclass_of ($ enumClass , \BackedEnum::class)) {
194- if (!isset (self ::$ enumValueCache [$ enumClass ])) {
195- self ::$ enumValueCache [$ enumClass ] = array_map (fn ($ case ) => $ case ->value , $ enumClass ::cases ());
198+ if (! isset (self ::$ enumValueCache [$ enumClass ])) {
199+ self ::$ enumValueCache [$ enumClass ] = array_map (fn ($ case ) => $ case ->value , $ enumClass ::cases ());
196200 }
197201
198- if (!\in_array ($ value , self ::$ enumValueCache [$ enumClass ], true )) {
202+ if (! \in_array ($ value , self ::$ enumValueCache [$ enumClass ], true )) {
199203 return ErrorFactory::createError ($ context . " must be a value of enum $ enumClass, " . TypeFormatter::formatGivenValue ($ value ) . ' given ' );
200204 }
205+
201206 return null ;
202207 }
203208 }
204209
205210 return null ;
206211 }
212+
207213 /**
208214 * Validates integer ranges (e.g. int<1, 100> or int<min, max>).
209215 */
0 commit comments