Created
October 19, 2024 01:29
-
-
Save ArrayIterator/dd25215a2fcbbbd7daff2ccb13faa6e9 to your computer and use it in GitHub Desktop.
The semantic version parser
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
class SemanticVersion implements JsonSerializable | |
{ | |
/** | |
* Regex pattern for semantic versioning | |
* eg: | |
* 1.2.3 | |
* v1.2.3 | |
* 1.2.3-beta | |
* 1.2.3-beta.1 | |
* 1.2.3-beta.1+build.1 | |
* 1.2.3+build.1 | |
* 1.2.3+build.1.2 | |
* | |
* contains array matched keys: | |
* { | |
* "prefix"?: "[a-zA-Z]+", | |
* "major": "[0-9]+", | |
* "minor": "[0-9]+", | |
* "patch": "[0-9]+", | |
* "release_separator"?: "[+\-]", // optional | |
* "release"?: "[a-zA-Z0-9]+([a-zA-Z0-9.+\-]*[a-zA-Z0-9])?", // optional the release version | |
* } | |
*/ | |
public const SEMANTIC_VERSION_REGEX = '^ | |
(?x) | |
(?<prefix>[a-zA-Z]+)? # optional prefix: eg : "v" in "v1.2.3" | |
(?P<major>[0-9]+) # major version | |
\.(?P<minor>[0-9]+) # minor version | |
\.(?P<patch>[0-9]+) # patch version | |
(?: | |
(?P<release_separator>[+\-]) | |
(?P<release> | |
[a-zA-Z0-9]+ # should start with a number or a letter | |
(?: | |
[a-zA-Z0-9.+\-]* # allow any number of letters, numbers, dots, plus and minus | |
[a-zA-Z0-9] # should end with a number or a letter | |
)? | |
) # release version | |
)? | |
$'; | |
/** | |
* The version string | |
* | |
* @var string | |
*/ | |
public readonly string $version; | |
/** | |
* Is the version string valid | |
* | |
* @var bool | |
*/ | |
public readonly bool $valid; | |
/** | |
* The major version | |
* | |
* @var int|null | |
*/ | |
public readonly ?int $major; | |
/** | |
* The minor version | |
* | |
* @var int|null | |
*/ | |
public readonly ?int $minor; | |
/** | |
* The patch version | |
* | |
* @var int|null | |
*/ | |
public readonly ?int $patch; | |
/** | |
* The release separator | |
* | |
* @var string|null | |
*/ | |
public readonly ?string $releaseSeparator; | |
/** | |
* The release version | |
* | |
* @var string|null | |
*/ | |
public readonly ?string $release; | |
/** | |
* SemanticVersion constructor. | |
* | |
* @param string $version | |
*/ | |
public function __construct(string $version) | |
{ | |
$this->version = trim($version); | |
preg_match('/' . self::SEMANTIC_VERSION_REGEX . '/', $this->version, $matches); | |
$this->valid = !empty($matches); | |
$this->major = is_array($matches) && isset($matches['major']) ? (int) $matches['major'] : null; | |
$this->minor = is_array($matches) && isset($matches['minor']) ? (int) $matches['minor'] : null; | |
$this->patch = is_array($matches) && isset($matches['patch']) ? (int) $matches['patch'] : null; | |
$this->releaseSeparator = is_array($matches) | |
&& isset($matches['release_separator']) | |
? $matches['release_separator'] | |
: null; | |
$this->release = is_array($matches) && isset($matches['release']) ? $matches['release'] : null; | |
} | |
public function __toString(): string | |
{ | |
return $this->version; | |
} | |
/** | |
* @return array{ | |
* version: string, | |
* valid: bool, | |
* major: int|null, | |
* minor: int|null, | |
* patch: int|null, | |
* release_separator: string|null, | |
* release: string|null | |
* } | |
*/ | |
public function toArray(): array | |
{ | |
return [ | |
'version' => $this->version, | |
'valid' => $this->valid, | |
'major' => $this->major, | |
'minor' => $this->minor, | |
'patch' => $this->patch, | |
'release_separator' => $this->releaseSeparator, | |
'release' => $this->release, | |
]; | |
} | |
/** | |
* @return array{ | |
* version: string, | |
* valid: bool, | |
* major: int|null, | |
* minor: int|null, | |
* patch: int|null, | |
* release_separator: string|null, | |
* release: string|null | |
* } | |
*/ | |
public function jsonSerialize(): array | |
{ | |
return $this->toArray(); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment