1<?php declare(strict_types=1); 2 3namespace PhpParser; 4 5/** 6 * A PHP version, representing only the major and minor version components. 7 */ 8class PhpVersion { 9 /** @var int Version ID in PHP_VERSION_ID format */ 10 public int $id; 11 12 /** @var int[] Minimum versions for builtin types */ 13 private const BUILTIN_TYPE_VERSIONS = [ 14 'array' => 50100, 15 'callable' => 50400, 16 'bool' => 70000, 17 'int' => 70000, 18 'float' => 70000, 19 'string' => 70000, 20 'iterable' => 70100, 21 'void' => 70100, 22 'object' => 70200, 23 'null' => 80000, 24 'false' => 80000, 25 'mixed' => 80000, 26 'never' => 80100, 27 'true' => 80200, 28 ]; 29 30 private function __construct(int $id) { 31 $this->id = $id; 32 } 33 34 /** 35 * Create a PhpVersion object from major and minor version components. 36 */ 37 public static function fromComponents(int $major, int $minor): self { 38 return new self($major * 10000 + $minor * 100); 39 } 40 41 /** 42 * Get the newest PHP version supported by this library. Support for this version may be partial, 43 * if it is still under development. 44 */ 45 public static function getNewestSupported(): self { 46 return self::fromComponents(8, 4); 47 } 48 49 /** 50 * Get the host PHP version, that is the PHP version we're currently running on. 51 */ 52 public static function getHostVersion(): self { 53 return self::fromComponents(\PHP_MAJOR_VERSION, \PHP_MINOR_VERSION); 54 } 55 56 /** 57 * Parse the version from a string like "8.1". 58 */ 59 public static function fromString(string $version): self { 60 if (!preg_match('/^(\d+)\.(\d+)/', $version, $matches)) { 61 throw new \LogicException("Invalid PHP version \"$version\""); 62 } 63 return self::fromComponents((int) $matches[1], (int) $matches[2]); 64 } 65 66 /** 67 * Check whether two versions are the same. 68 */ 69 public function equals(PhpVersion $other): bool { 70 return $this->id === $other->id; 71 } 72 73 /** 74 * Check whether this version is greater than or equal to the argument. 75 */ 76 public function newerOrEqual(PhpVersion $other): bool { 77 return $this->id >= $other->id; 78 } 79 80 /** 81 * Check whether this version is older than the argument. 82 */ 83 public function older(PhpVersion $other): bool { 84 return $this->id < $other->id; 85 } 86 87 /** 88 * Check whether this is the host PHP version. 89 */ 90 public function isHostVersion(): bool { 91 return $this->equals(self::getHostVersion()); 92 } 93 94 /** 95 * Check whether this PHP version supports the given builtin type. Type name must be lowercase. 96 */ 97 public function supportsBuiltinType(string $type): bool { 98 $minVersion = self::BUILTIN_TYPE_VERSIONS[$type] ?? null; 99 return $minVersion !== null && $this->id >= $minVersion; 100 } 101 102 /** 103 * Whether this version supports [] array literals. 104 */ 105 public function supportsShortArraySyntax(): bool { 106 return $this->id >= 50400; 107 } 108 109 /** 110 * Whether this version supports [] for destructuring. 111 */ 112 public function supportsShortArrayDestructuring(): bool { 113 return $this->id >= 70100; 114 } 115 116 /** 117 * Whether this version supports flexible heredoc/nowdoc. 118 */ 119 public function supportsFlexibleHeredoc(): bool { 120 return $this->id >= 70300; 121 } 122 123 /** 124 * Whether this version supports trailing commas in parameter lists. 125 */ 126 public function supportsTrailingCommaInParamList(): bool { 127 return $this->id >= 80000; 128 } 129 130 /** 131 * Whether this version allows "$var =& new Obj". 132 */ 133 public function allowsAssignNewByReference(): bool { 134 return $this->id < 70000; 135 } 136 137 /** 138 * Whether this version allows invalid octals like "08". 139 */ 140 public function allowsInvalidOctals(): bool { 141 return $this->id < 70000; 142 } 143 144 /** 145 * Whether this version allows DEL (\x7f) to occur in identifiers. 146 */ 147 public function allowsDelInIdentifiers(): bool { 148 return $this->id < 70100; 149 } 150 151 /** 152 * Whether this version supports yield in expression context without parentheses. 153 */ 154 public function supportsYieldWithoutParentheses(): bool { 155 return $this->id >= 70000; 156 } 157 158 /** 159 * Whether this version supports unicode escape sequences in strings. 160 */ 161 public function supportsUnicodeEscapes(): bool { 162 return $this->id >= 70000; 163 } 164} 165