1: <?php declare(strict_types = 1);
2:
3: namespace PHPStan\Php;
4:
5: use function floor;
6:
7: /** @api */
8: class PhpVersion
9: {
10:
11: public const SOURCE_RUNTIME = 1;
12: public const SOURCE_CONFIG = 2;
13: public const SOURCE_COMPOSER_PLATFORM_PHP = 3;
14: public const SOURCE_UNKNOWN = 4;
15:
16: /**
17: * @param self::SOURCE_* $source
18: */
19: public function __construct(private int $versionId, private int $source = self::SOURCE_UNKNOWN)
20: {
21: }
22:
23: public function getSourceLabel(): string
24: {
25: switch ($this->source) {
26: case self::SOURCE_RUNTIME:
27: return 'runtime';
28: case self::SOURCE_CONFIG:
29: return 'config';
30: case self::SOURCE_COMPOSER_PLATFORM_PHP:
31: return 'config.platform.php in composer.json';
32: }
33:
34: return 'unknown';
35: }
36:
37: public function getVersionId(): int
38: {
39: return $this->versionId;
40: }
41:
42: public function getVersionString(): string
43: {
44: $first = (int) floor($this->versionId / 10000);
45: $second = (int) floor(($this->versionId % 10000) / 100);
46: $third = (int) floor($this->versionId % 100);
47:
48: return $first . '.' . $second . ($third !== 0 ? '.' . $third : '');
49: }
50:
51: public function supportsNullCoalesceAssign(): bool
52: {
53: return $this->versionId >= 70400;
54: }
55:
56: public function supportsParameterContravariance(): bool
57: {
58: return $this->versionId >= 70400;
59: }
60:
61: public function supportsReturnCovariance(): bool
62: {
63: return $this->versionId >= 70400;
64: }
65:
66: public function supportsNoncapturingCatches(): bool
67: {
68: return $this->versionId >= 80000;
69: }
70:
71: public function supportsNativeUnionTypes(): bool
72: {
73: return $this->versionId >= 80000;
74: }
75:
76: public function deprecatesRequiredParameterAfterOptional(): bool
77: {
78: return $this->versionId >= 80000;
79: }
80:
81: public function deprecatesRequiredParameterAfterOptionalNullableAndDefaultNull(): bool
82: {
83: return $this->versionId >= 80100;
84: }
85:
86: public function deprecatesRequiredParameterAfterOptionalUnionOrMixed(): bool
87: {
88: return $this->versionId >= 80300;
89: }
90:
91: public function supportsLessOverridenParametersWithVariadic(): bool
92: {
93: return $this->versionId >= 80000;
94: }
95:
96: public function supportsThrowExpression(): bool
97: {
98: return $this->versionId >= 80000;
99: }
100:
101: public function supportsClassConstantOnExpression(): bool
102: {
103: return $this->versionId >= 80000;
104: }
105:
106: public function supportsLegacyConstructor(): bool
107: {
108: return $this->versionId < 80000;
109: }
110:
111: public function supportsPromotedProperties(): bool
112: {
113: return $this->versionId >= 80000;
114: }
115:
116: public function supportsParameterTypeWidening(): bool
117: {
118: return $this->versionId >= 70200;
119: }
120:
121: public function supportsUnsetCast(): bool
122: {
123: return $this->versionId < 80000;
124: }
125:
126: public function supportsNamedArguments(): bool
127: {
128: return $this->versionId >= 80000;
129: }
130:
131: public function throwsTypeErrorForInternalFunctions(): bool
132: {
133: return $this->versionId >= 80000;
134: }
135:
136: public function throwsValueErrorForInternalFunctions(): bool
137: {
138: return $this->versionId >= 80000;
139: }
140:
141: public function supportsHhPrintfSpecifier(): bool
142: {
143: return $this->versionId >= 80000;
144: }
145:
146: public function isEmptyStringValidAliasForNoneInMbSubstituteCharacter(): bool
147: {
148: return $this->versionId < 80000;
149: }
150:
151: public function supportsAllUnicodeScalarCodePointsInMbSubstituteCharacter(): bool
152: {
153: return $this->versionId >= 70200;
154: }
155:
156: public function isNumericStringValidArgInMbSubstituteCharacter(): bool
157: {
158: return $this->versionId < 80000;
159: }
160:
161: public function isNullValidArgInMbSubstituteCharacter(): bool
162: {
163: return $this->versionId >= 80000;
164: }
165:
166: public function isInterfaceConstantImplicitlyFinal(): bool
167: {
168: return $this->versionId < 80100;
169: }
170:
171: public function supportsFinalConstants(): bool
172: {
173: return $this->versionId >= 80100;
174: }
175:
176: public function supportsReadOnlyProperties(): bool
177: {
178: return $this->versionId >= 80100;
179: }
180:
181: public function supportsEnums(): bool
182: {
183: return $this->versionId >= 80100;
184: }
185:
186: public function supportsPureIntersectionTypes(): bool
187: {
188: return $this->versionId >= 80100;
189: }
190:
191: public function supportsCaseInsensitiveConstantNames(): bool
192: {
193: return $this->versionId < 80000;
194: }
195:
196: public function hasStricterRoundFunctions(): bool
197: {
198: return $this->versionId >= 80000;
199: }
200:
201: public function hasTentativeReturnTypes(): bool
202: {
203: return $this->versionId >= 80100;
204: }
205:
206: public function supportsFirstClassCallables(): bool
207: {
208: return $this->versionId >= 80100;
209: }
210:
211: public function supportsArrayUnpackingWithStringKeys(): bool
212: {
213: return $this->versionId >= 80100;
214: }
215:
216: public function throwsOnInvalidMbStringEncoding(): bool
217: {
218: return $this->versionId >= 80000;
219: }
220:
221: public function supportsPassNoneEncodings(): bool
222: {
223: return $this->versionId < 70300;
224: }
225:
226: public function producesWarningForFinalPrivateMethods(): bool
227: {
228: return $this->versionId >= 80000;
229: }
230:
231: public function deprecatesDynamicProperties(): bool
232: {
233: return $this->versionId >= 80200;
234: }
235:
236: public function strSplitReturnsEmptyArray(): bool
237: {
238: return $this->versionId >= 80200;
239: }
240:
241: public function supportsDisjunctiveNormalForm(): bool
242: {
243: return $this->versionId >= 80200;
244: }
245:
246: public function serializableRequiresMagicMethods(): bool
247: {
248: return $this->versionId >= 80100;
249: }
250:
251: public function arrayFunctionsReturnNullWithNonArray(): bool
252: {
253: return $this->versionId < 80000;
254: }
255:
256: // see https://www.php.net/manual/en/migration80.incompatible.php#migration80.incompatible.core.string-number-comparision
257: public function castsNumbersToStringsOnLooseComparison(): bool
258: {
259: return $this->versionId >= 80000;
260: }
261:
262: public function supportsCallableInstanceMethods(): bool
263: {
264: return $this->versionId < 80000;
265: }
266:
267: public function supportsJsonValidate(): bool
268: {
269: return $this->versionId >= 80300;
270: }
271:
272: public function supportsConstantsInTraits(): bool
273: {
274: return $this->versionId >= 80200;
275: }
276:
277: public function supportsNativeTypesInClassConstants(): bool
278: {
279: return $this->versionId >= 80300;
280: }
281:
282: public function supportsAbstractTraitMethods(): bool
283: {
284: return $this->versionId >= 80000;
285: }
286:
287: public function supportsOverrideAttribute(): bool
288: {
289: return $this->versionId >= 80300;
290: }
291:
292: public function supportsDynamicClassConstantFetch(): bool
293: {
294: return $this->versionId >= 80300;
295: }
296:
297: public function supportsReadOnlyClasses(): bool
298: {
299: return $this->versionId >= 80200;
300: }
301:
302: public function supportsReadOnlyAnonymousClasses(): bool
303: {
304: return $this->versionId >= 80300;
305: }
306:
307: public function supportsNeverReturnTypeInArrowFunction(): bool
308: {
309: return $this->versionId >= 80200;
310: }
311:
312: }
313: