Repository: PHLAK/SemVer
Branch: master
Commit: bf9c3ca45511
Files: 21
Total size: 48.9 KB
Directory structure:
gitextract_fljnwk0f/
├── .editorconfig
├── .gitattributes
├── .github/
│ ├── FUNDING.yml
│ ├── dependabot.yml
│ └── workflows/
│ └── test-suite.yaml
├── .gitignore
├── .php-cs-fixer.dist.php
├── LICENSE
├── Makefile
├── README.md
├── composer.json
├── phpstan-ignores.neon
├── phpstan.neon.dist
├── phpunit.xml
├── src/
│ ├── Enums/
│ │ └── Compare.php
│ ├── Exceptions/
│ │ └── InvalidVersionException.php
│ ├── Support/
│ │ └── helpers.php
│ ├── Traits/
│ │ ├── Comparable.php
│ │ └── Incrementable.php
│ └── Version.php
└── tests/
└── VersionTest.php
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.json]
indent_style = space
indent_size = 4
[*.md]
trim_trailing_whitespace = false
indent_size = 4
[*.{yml,yaml}]
indent_size = 2
indent_style = space
================================================
FILE: .gitattributes
================================================
tests export-ignore
.gitattributes export-ignore
.gitignore export-ignore
.php_cs.dist export-ignore
.travis.yml export-ignore
phpunit.xml export-ignore
================================================
FILE: .github/FUNDING.yml
================================================
github: PHLAK
patreon: PHLAK
custom: https://paypal.me/ChrisKankiewicz
================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
- package-ecosystem: composer
directory: "/"
schedule:
interval: monthly
timezone: US/Arizona
open-pull-requests-limit: 10
assignees:
- PHLAK
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: monthly
timezone: US/Arizona
assignees:
- PHLAK
================================================
FILE: .github/workflows/test-suite.yaml
================================================
name: SemVer Test Suite
on: [push, pull_request, workflow_dispatch]
jobs:
coding-standards:
name: Coding Standards
runs-on: 'ubuntu-latest'
env:
PHP_CS_FIXER_IGNORE_ENV: 1
steps:
- name: Checkout Repository
uses: actions/checkout@v5
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.4'
- name: Install PHP Dependencies
run: composer install --no-interaction --no-progress --no-scripts --prefer-dist
- name: Verify Coding Standards
run: vendor/bin/php-cs-fixer fix --diff --dry-run
static-analysis:
name: Static Analysis
runs-on: 'ubuntu-latest'
steps:
- name: Checkout Repository
uses: actions/checkout@v5
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.4'
- name: Install PHP Dependencies
run: composer install --no-interaction --no-progress --no-scripts --prefer-dist
- name: Run Static Analysis
run: vendor/bin/phpstan analyze
tests:
name: Tests
runs-on: 'ubuntu-latest'
strategy:
matrix:
php-versions: ['8.1', '8.2', '8.3', '8.4']
steps:
- name: Checkout Repository
uses: actions/checkout@v5
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
coverage: xdebug
- name: Install PHP Dependencies
run: composer install --no-interaction --no-progress --no-scripts --prefer-dist
- name: Run Tests
run: vendor/bin/phpunit --coverage-text
================================================
FILE: .gitignore
================================================
/.php-cs-fixer.cache
/.phpunit.cache
/composer.lock
/vendor/
================================================
FILE: .php-cs-fixer.dist.php
================================================
<?php
require __DIR__ . '/vendor/autoload.php';
$finder = PhpCsFixer\Finder::create()->in([
__DIR__ . DIRECTORY_SEPARATOR . 'src',
__DIR__ . DIRECTORY_SEPARATOR . 'tests',
]);
return PHLAK\CodingStandards\ConfigFactory::make($finder);
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2024 Chris Kankiewicz <Chris@ChrisKankiewicz.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: Makefile
================================================
dev development: # Build application for development
@composer install --no-interaction
prod production: # Build application for production
@composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader
test: # Run coding standards/static analysis checks and tests
@vendor/bin/php-cs-fixer fix --diff --dry-run \
&& vendor/bin/phpstan analyze \
&& vendor/bin/phpunit --coverage-text
coverage: # Generate an HTML coverage report
@vendor/bin/phpunit --coverage-html .coverage
================================================
FILE: README.md
================================================
SemVer
======
<p align="center">
<img src="semver.png" alt="SemVer" width="50%">
</p>
<p align="center">
<a href="http://semver.org">Semantic versioning</a> helper library
• Created by <a href="https://www.ChrisKankiewicz.com">Chris Kankiewicz</a> (<a href="https://bsky.app/profile/phlak.dev">@phlak.dev</a>)
</p>
<p align="center">
<a href="https://github.com/PHLAK/SemVer/discussions"><img src="https://img.shields.io/badge/Join_the-Community-7b16ff.svg?style=for-the-badge" alt="Join our Community"></a>
<a href="https://github.com/users/PHLAK/sponsorship"><img src="https://img.shields.io/badge/Become_a-Sponsor-cc4195.svg?style=for-the-badge" alt="Become a Sponsor"></a>
<a href="https://paypal.me/ChrisKankiewicz"><img src="https://img.shields.io/badge/Make_a-Donation-006bb6.svg?style=for-the-badge" alt="One-time Donation"></a>
<br>
<a href="https://packagist.org/packages/PHLAK/SemVer"><img src="https://img.shields.io/packagist/v/PHLAK/SemVer.svg?style=flat-square" alt="Latest Stable Version"></a>
<a href="https://packagist.org/packages/PHLAK/SemVer"><img src="https://img.shields.io/packagist/dt/PHLAK/SemVer.svg?style=flat-square" alt="Total Downloads"></a>
<a href="https://packagist.org/packages/PHLAK/SemVer"><img src="https://img.shields.io/packagist/l/PHLAK/SemVer.svg?style=flat-square" alt="License"></a>
<a href="https://github.com/PHLAK/SemVer/actions"><img src="https://img.shields.io/github/actions/workflow/status/PHLAK/SemVer/test-suite.yaml?style=flat-square&label=tests" alt="Tests Status"></a>
</p>
---
Requirements
------------
- [PHP](https://php.net) >= 8.1
Installation
------------
```bash
composer require phlak/semver
```
Initializing
------------
```php
use PHLAK\SemVer;
$version = new SemVer\Version(); // Initilializes to '0.1.0'
```
Or initialize with a custom version by passing a version string on creation.
Accepts any valid semantic version string with or without a preceding `v`.
```php
$version = new SemVer\Version('v1.2.3-alpha.5+sha.8d31ff4');
```
Or parse an incomple version string with the static `Version::parse()` constructor.
```php
$version = SemVer\Version::parse('v1') // Initializes to '1.0.0'
$version = SemVer\Version::parse('v1.2') // Initializes to '1.2.0'
```
Usage
-----
#### Retrieve the version or individual values
```php
$version = new SemVer\Version('v1.2.3-beta.4+007');
echo $version; // '1.2.3-beta.4+007'
echo $version->major; // 1
echo $version->minor; // 2
echo $version->patch; // 3
echo $version->preRelease; // 'beta.4'
echo $version->build; // '007'
```
#### Increment the version
```php
$version = new SemVer\Version('v1.2.3');
$version->incrementMajor(); // v1.2.3 -> v2.0.0
$version->incrementMinor(); // v1.2.3 -> v1.3.0
$version->incrementPatch(); // v1.2.3 -> v1.2.4
$version->incrementPreRelease(); // v1.2.3-alpha.5 -> v1.2.3-alpha.6
```
#### Set (override) the version or individual values
```php
$version = new SemVer\Version();
$version->setVersion('v1.2.3'); // v1.2.3
$version->setMajor(3); // v1.2.3 -> v3.0.0
$version->setMinor(5); // v1.2.3 -> v1.5.0
$version->setPatch(7); // v1.2.3 -> 1.2.7
$version->setPreRelease('rc.2'); // v1.2.3 -> v1.2.3-rc.2
$version->setBuild('007'); // v1.2.3 -> v1.2.3+007
```
#### Clear pre-release / build values
```php
$version->setPreRelease(null); // v1.2.3-rc.2 -> v1.2.3
$version->setBuild(null); // v1.2.3+007 -> v1.2.3
```
#### Check for pre-release / build values
```php
$version->isPreRelease();
$version->hasBuild();
```
#### Compare two SemVer objects
```php
$version1 = new SemVer\Version('v1.2.3');
$version2 = new SemVer\Version('v3.2.1');
$version1->gt($version2); // false
$version1->lt($version2); // true
$version1->eq($version2); // false
$version1->neq($version2); // true
$version1->gte($version2); // false
$version1->lte($version2); // true
```
##### Limit comparison to the major version only
Ignores the minor, patch and pre-release versions completely
```php
$version1 = new SemVer\Version('v1.2.3-alpha.4');
$version2 = new SemVer\Version('v1.3.4-alpha.5');
$version1->gt($version2, Compare::MAJOR); // false
$version1->lt($version2, Compare::MAJOR); // false
$version1->eq($version2, Compare::MAJOR); // true
$version1->neq($version2, Compare::MAJOR); // false
$version1->gte($version2, Compare::MAJOR); // true
$version1->lte($version2, Compare::MAJOR); // true
```
##### Limit comparison to the major and minor versions only
Ignores the patch and pre-release versions completely
```php
$version1 = new SemVer\Version('v1.2.3-alpha.4');
$version2 = new SemVer\Version('v1.2.4-alpha.5');
$version1->gt($version2, Compare::MINOR); // false
$version1->lt($version2, Compare::MINOR); // false
$version1->eq($version2, Compare::MINOR); // true
$version1->neq($version2, Compare::MINOR); // false
$version1->gte($version2, Compare::MINOR); // true
$version1->lte($version2, Compare::MINOR); // true
```
##### Limit comparison to the major, minor and patch versions only
Ignores the pre-release version completely
```php
$version1 = new SemVer\Version('v1.2.3-alpha.4');
$version2 = new SemVer\Version('v1.2.3-alpha.5');
$version1->gt($version2, Compare::PATCH); // false
$version1->lt($version2, Compare::PATCH); // false
$version1->eq($version2, Compare::PATCH); // true
$version1->neq($version2, Compare::PATCH); // false
$version1->gte($version2, Compare::PATCH); // true
$version1->lte($version2, Compare::PATCH); // true
```
Troubleshooting
---------------
For general help and support join our [GitHub Discussions](https://github.com/PHLAK/SemVer/discussions) or reach out on [Bluesky](https://bsky.app/profile/phlak.dev).
Please report bugs to the [GitHub Issue Tracker](https://github.com/PHLAK/SemVer/issues).
Copyright
---------
This project is liscensed under the [MIT License](https://github.com/PHLAK/SemVer/blob/master/LICENSE).
================================================
FILE: composer.json
================================================
{
"name": "phlak/semver",
"description": "Semantic versioning helper library",
"type": "library",
"license": "MIT",
"authors": [
{
"name": "Chris Kankiewicz",
"email": "Chris@ChrisKankiewicz.com"
}
],
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/PHLAK"
},
{
"type": "paypal",
"url": "https://paypal.me/ChrisKankiewicz"
}
],
"support": {
"issues": "https://github.com/PHLAK/SemVer/issues"
},
"require": {
"php": "^8.1 || ^8.2 || ^8.3 || ^8.4"
},
"require-dev": {
"phlak/coding-standards": "^4.0",
"phpstan/phpstan": "^2.0",
"yoast/phpunit-polyfills": "^4.0"
},
"autoload": {
"psr-4": {
"PHLAK\\SemVer\\": "src/"
},
"files": ["src/Support/helpers.php"]
},
"autoload-dev": {
"psr-4": {
"PHLAK\\Semver\\Tests\\": "tests/"
}
},
"config": {
"sort-packages": true,
"optimize-autoloader": true,
"allow-plugins": {
"composer/package-versions-deprecated": true
}
}
}
================================================
FILE: phpstan-ignores.neon
================================================
parameters:
ignoreErrors:
- message: "/^Method .+ throws checked exception .+ but it's missing from the PHPDoc @throws tag.$/"
path: tests/*
================================================
FILE: phpstan.neon.dist
================================================
parameters:
paths:
- src
- tests
level: max
checkFunctionNameCase: true
exceptions:
implicitThrows: false
check:
missingCheckedExceptionInThrows: true
tooWideThrowType: true
uncheckedExceptionClasses:
- 'RuntimeException'
- 'PHPUnit\Framework\Exception'
includes:
- phpstan-ignores.neon
================================================
FILE: phpunit.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php" colors="true"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd"
>
<testsuites>
<testsuite name="PHLAK/SemVer Test Suite">
<directory>tests/</directory>
</testsuite>
</testsuites>
<source>
<include>
<directory suffix=".php">src/</directory>
</include>
</source>
</phpunit>
================================================
FILE: src/Enums/Compare.php
================================================
<?php
namespace PHLAK\SemVer\Enums;
enum Compare
{
case FULL;
case MAJOR;
case MINOR;
case PATCH;
}
================================================
FILE: src/Exceptions/InvalidVersionException.php
================================================
<?php
namespace PHLAK\SemVer\Exceptions;
use Exception;
class InvalidVersionException extends Exception {}
================================================
FILE: src/Support/helpers.php
================================================
<?php
use PHLAK\SemVer\Version;
if (! function_exists('semver')) {
/**
* Create a SemVer version object.
*
* @throws \PHLAK\SemVer\Exceptions\InvalidVersionException
*/
function semver(string $string): Version
{
return new PHLAK\SemVer\Version($string);
}
}
================================================
FILE: src/Traits/Comparable.php
================================================
<?php
namespace PHLAK\SemVer\Traits;
use PHLAK\SemVer\Enums\Compare;
use PHLAK\SemVer\Version;
trait Comparable
{
/**
* Compare two versions. Returns -1, 0 or 1 if the first version is less
* than, equal to or greater than the second version respectively.
*
* @param Version $version1 An instance of SemVer/Version
* @param Version $version2 An instance of SemVer/Version
*/
public static function compare(Version $version1, Version $version2, Compare $comparison = Compare::FULL): int
{
[$v1, $v2] = match ($comparison) {
Compare::MAJOR => [[$version1->major], [$version2->major]],
Compare::MINOR => [[$version1->major, $version1->minor], [$version2->major, $version2->minor]],
default => [[$version1->major, $version1->minor, $version1->patch], [$version2->major, $version2->minor, $version2->patch]]
};
$baseComparison = $v1 <=> $v2;
if ($baseComparison !== 0 || $comparison !== Compare::FULL) {
return $baseComparison;
}
if ($version1->preRelease !== null && $version2->preRelease === null) {
return -1;
}
if ($version1->preRelease === null && $version2->preRelease !== null) {
return 1;
}
$v1preReleaseParts = explode('.', $version1->preRelease ?? '');
$v2preReleaseParts = explode('.', $version2->preRelease ?? '');
$preReleases1 = array_pad($v1preReleaseParts, count($v2preReleaseParts), null);
$preReleases2 = array_pad($v2preReleaseParts, count($v1preReleaseParts), null);
return $preReleases1 <=> $preReleases2;
}
/**
* Check if this Version object is greater than another.
*
* @param Version $version An instance of SemVer/Version
*
* @return bool True if this Version object is greater than the comparing
* object, otherwise false
*/
public function gt(Version $version, Compare $comparison = Compare::FULL): bool
{
return self::compare($this, $version, $comparison) > 0;
}
/**
* Check if this Version object is less than another.
*
* @param Version $version An instance of SemVer/Version
*
* @return bool True if this Version object is less than the comparing
* object, otherwise false
*/
public function lt(Version $version, Compare $comparison = Compare::FULL): bool
{
return self::compare($this, $version, $comparison) < 0;
}
/**
* Check if this Version object is equal to than another.
*
* @param Version $version An instance of SemVer/Version
*
* @return bool True if this Version object is equal to the comparing
* object, otherwise false
*/
public function eq(Version $version, Compare $comparison = Compare::FULL): bool
{
return self::compare($this, $version, $comparison) === 0;
}
/**
* Check if this Version object is not equal to another.
*
* @param Version $version An instance of SemVer/Version
*
* @return bool True if this Version object is not equal to the comparing
* object, otherwise false
*/
public function neq(Version $version, Compare $comparison = Compare::FULL): bool
{
return self::compare($this, $version, $comparison) !== 0;
}
/**
* Check if this Version object is greater than or equal to another.
*
* @param Version $version An instance of SemVer/Version
*
* @return bool True if this Version object is greater than or equal to the
* comparing object, otherwise false
*/
public function gte(Version $version, Compare $comparison = Compare::FULL): bool
{
return self::compare($this, $version, $comparison) >= 0;
}
/**
* Check if this Version object is less than or equal to another.
*
* @param Version $version An instance of SemVer/Version
*
* @return bool True if this Version object is less than or equal to the
* comparing object, otherwise false
*/
public function lte(Version $version, Compare $comparison = Compare::FULL): bool
{
return self::compare($this, $version, $comparison) <= 0;
}
}
================================================
FILE: src/Traits/Incrementable.php
================================================
<?php
namespace PHLAK\SemVer\Traits;
trait Incrementable
{
/**
* Increment the major version value by one.
*
* @return static This Version object
*/
public function incrementMajor(): static
{
$this->setMajor($this->major + 1);
return $this;
}
/**
* Increment the minor version value by one.
*
* @return static This Version object
*/
public function incrementMinor(): static
{
$this->setMinor($this->minor + 1);
return $this;
}
/**
* Increment the patch version value by one.
*
* @return static This Version object
*/
public function incrementPatch(): static
{
$this->setPatch($this->patch + 1);
return $this;
}
/**
* Increment the pre-release version value by one.
*
* @return static This Version object
*/
public function incrementPreRelease(): static
{
if (empty($this->preRelease)) {
$this->incrementPatch();
$this->setPreRelease('1');
return $this;
}
$identifiers = explode('.', $this->preRelease);
if (! is_numeric(end($identifiers))) {
$this->setPreRelease(implode('.', [$this->preRelease, '1']));
return $this;
}
array_push($identifiers, (string) ((int) array_pop($identifiers) + 1));
$this->setPreRelease(implode('.', $identifiers));
return $this;
}
}
================================================
FILE: src/Version.php
================================================
<?php
namespace PHLAK\SemVer;
use JsonSerializable;
use PHLAK\SemVer\Exceptions\InvalidVersionException;
use PHLAK\SemVer\Traits\Comparable;
use PHLAK\SemVer\Traits\Incrementable;
/**
* @property int $major Major release number
* @property int $minor Minor release number
* @property int $patch Patch release number
* @property string|null $preRelease Pre-release value
* @property string|null $build Build release value
*/
class Version implements JsonSerializable
{
use Comparable;
use Incrementable;
/** @var int Major release number */
protected $major;
/** @var int Minor release number */
protected $minor;
/** @var int Patch release number */
protected $patch;
/** @var string|null Pre-release value */
protected $preRelease;
/** @var string|null Build release value */
protected $build;
/**
* Class constructor, runs on object creation.
*
* @param string $version Version string
*
* @throws \PHLAK\SemVer\Exceptions\InvalidVersionException
*/
final public function __construct(string $version = '0.1.0')
{
$this->setVersion($version);
}
/**
* Magic get method; provides access to version properties.
*
* @param string $property Version property
*
* @return mixed Version property value
*/
public function __get(string $property)
{
return $this->$property;
}
/**
* Magic toString method; allows object interaction as if it were a string.
*
* @return string Current version string
*/
public function __toString(): string
{
$version = implode('.', [$this->major, $this->minor, $this->patch]);
if (! empty($this->preRelease)) {
$version .= '-' . $this->preRelease;
}
if (! empty($this->build)) {
$version .= '+' . $this->build;
}
return $version;
}
/**
* Attempt to parse an incomplete version string.
*
* Examples: 'v1', 'v1.2', 'v1-beta.4', 'v1.3+007'
*
* @param string $version Version string
*
* @throws \PHLAK\SemVer\Exceptions\InvalidVersionException
*
* @return static This Version object
*/
public static function parse(string $version): static
{
$semverRegex = '/^v?(?<major>\d+)(?:\.(?<minor>\d+)(?:\.(?<patch>\d+))?)?(?:-(?<pre_release>[0-9A-Za-z-.]+))?(?:\+(?<build>[0-9A-Za-z-.]+)?)?$/';
if (! preg_match($semverRegex, $version, $matches, PREG_UNMATCHED_AS_NULL)) {
throw new InvalidVersionException('Invalid semantic version string provided');
}
$version = sprintf('%s.%s.%s', $matches['major'], $matches['minor'] ?? 0, $matches['patch'] ?? 0);
if (! empty($matches['pre_release'])) {
$version .= '-' . $matches['pre_release'];
}
if (! empty($matches['build'])) {
$version .= '+' . $matches['build'];
}
return new static($version);
}
/** Serialize version to JSON. */
public function jsonSerialize(): mixed
{
return (string) $this;
}
/**
* Set (override) the entire version value.
*
* @param string $version Version string
*
* @throws \PHLAK\SemVer\Exceptions\InvalidVersionException
*
* @return static This Version object
*/
public function setVersion(string $version): static
{
$semverRegex = '/^v?(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)(?:-(?<pre_release>[0-9A-Za-z-.]+))?(?:\+(?<build>[0-9A-Za-z-.]+)?)?$/';
if (! preg_match($semverRegex, $version, $matches, PREG_UNMATCHED_AS_NULL)) {
throw new InvalidVersionException('Invalid semantic version string provided');
}
$this->major = (int) $matches['major'];
$this->minor = (int) $matches['minor'];
$this->patch = (int) $matches['patch'];
$this->preRelease = $matches['pre_release'] ?? null;
$this->build = $matches['build'] ?? null;
return $this;
}
/**
* Set the major version to a custom value.
*
* @param int $value Positive integer value
*
* @return static This Version object
*/
public function setMajor(int $value): static
{
$this->major = $value;
$this->setMinor(0);
return $this;
}
/**
* Set the minor version to a custom value.
*
* @param int $value Positive integer value
*
* @return static This Version object
*/
public function setMinor(int $value): static
{
$this->minor = $value;
$this->setPatch(0);
return $this;
}
/**
* Set the patch version to a custom value.
*
* @param int $value Positive integer value
*
* @return static This Version object
*/
public function setPatch(int $value): static
{
$this->patch = $value;
$this->setPreRelease(null);
$this->setBuild(null);
return $this;
}
/**
* Set the pre-release string to a custom value.
*
* @param string|null $value A new pre-release value
*
* @return static This Version object
*/
public function setPreRelease($value): static
{
$this->preRelease = $value;
return $this;
}
/**
* Set the build string to a custom value.
*
* @param string|null $value A new build value
*
* @return static This Version object
*/
public function setBuild($value): static
{
$this->build = $value;
return $this;
}
/**
* Get the version string prefixed with a custom string.
*
* @param string $prefix String to prepend to the version string
* (default: 'v')
*
* @return string Prefixed version string
*/
public function prefix(string $prefix = 'v'): string
{
return $prefix . (string) $this;
}
/**
* Determine if the version is a pre-release.
*
* @return bool Returns true if the version is a pre-release, false otherwise
*/
public function isPreRelease(): bool
{
return ! empty($this->preRelease);
}
/**
* Determine if the version has a build string.
*
* @return bool Returns true if the version has a build string, false otherwise
*/
public function hasBuild(): bool
{
return ! empty($this->build);
}
}
================================================
FILE: tests/VersionTest.php
================================================
<?php
namespace PHLAK\SemVer\Tests;
use JsonSerializable;
use PHLAK\SemVer;
use PHLAK\SemVer\Enums\Compare;
use PHLAK\SemVer\Exceptions\InvalidVersionException;
use PHLAK\SemVer\Traits\Comparable;
use PHLAK\SemVer\Traits\Incrementable;
use PHLAK\SemVer\Version;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\CoversTrait;
use PHPUnit\Framework\Attributes\Test;
use Yoast\PHPUnitPolyfills\TestCases\TestCase;
#[CoversClass(Version::class)]
#[CoversTrait(Comparable::class)]
#[CoversTrait(Incrementable::class)]
class VersionTest extends TestCase
{
/** @return array<array<int, mixed>> */
public static function pre_release_comparison_provider(): array
{
return [
['v1.3.37', 'v1.3.37-alpha'],
['v1.3.37', 'v1.3.37-alpha.5+007'],
['v1.3.0', 'v1.3.0-beta'],
['v1.0.0', 'v1.0.0-rc1'],
// Test cases from http://semver.org
['1.0.0', '1.0.0-rc.1'],
['1.0.0-rc.1', '1.0.0-beta.11'],
['1.0.0-beta.11', '1.0.0-beta.2'],
['1.0.0-beta.2', '1.0.0-beta'],
['1.0.0-beta', '1.0.0-alpha.beta'],
['1.0.0-alpha.beta', '1.0.0-alpha.1'],
['1.0.0-alpha.1', '1.0.0-alpha'],
];
}
#[Test]
public function it_can_be_initialized(): void
{
$version = new SemVer\Version('v1.3.37');
$this->assertInstanceOf(SemVer\Version::class, $version);
}
#[Test]
public function it_can_be_initialized_with_the_helper_function(): void
{
$version = semver('v1.3.37');
$this->assertInstanceOf(SemVer\Version::class, $version);
}
#[Test]
public function it_throws_a_runtime_exception_for_an_invalid_version(): void
{
$this->expectException(InvalidVersionException::class);
new SemVer\Version('not.a.version');
}
#[Test]
public function it_can_parse_an_incomplete_version_string(): void
{
$this->assertEquals('1.0.0', (string) SemVer\Version::parse('v1'));
$this->assertEquals('1.3.0', (string) SemVer\Version::parse('v1.3'));
$this->assertEquals('1.3.37', (string) SemVer\Version::parse('v1.3.37'));
$this->assertEquals('1.0.0-alpha.5', (string) SemVer\Version::parse('v1-alpha.5'));
$this->assertEquals('1.3.0-alpha.5', (string) SemVer\Version::parse('v1.3-alpha.5'));
$this->assertEquals('1.3.37-alpha.5', (string) SemVer\Version::parse('v1.3.37-alpha.5'));
$this->assertEquals('1.0.0+007', (string) SemVer\Version::parse('v1+007'));
$this->assertEquals('1.3.0+007', (string) SemVer\Version::parse('v1.3+007'));
$this->assertEquals('1.3.37+007', (string) SemVer\Version::parse('v1.3.37+007'));
}
#[Test]
public function it_throws_a_runtime_exception_when_parsing_an_invalid_version(): void
{
$this->expectException(InvalidVersionException::class);
SemVer\Version::parse('not.a.version');
}
#[Test]
public function it_can_set_and_retrieve_a_version(): void
{
$version = new SemVer\Version('v1.3.37');
$version->setVersion('v2.4.48');
$this->assertEquals('2.4.48', (string) $version);
}
#[Test]
public function it_can_return_a_prefixed_version_string(): void
{
$version = new SemVer\Version('v1.3.37');
$this->assertEquals('v1.3.37', $version->prefix());
$this->assertEquals('x1.3.37', $version->prefix('x'));
}
#[Test]
public function it_can_be_cast_to_a_string(): void
{
$this->assertEquals('1.3.37', (string) new SemVer\Version('v1.3.37'));
$this->assertEquals('1.3.37-alpha.5', (string) new SemVer\Version('v1.3.37-alpha.5'));
$this->assertEquals('1.3.37+007', (string) new SemVer\Version('v1.3.37+007'));
$this->assertEquals('1.3.37-alpha.5+007', (string) new SemVer\Version('v1.3.37-alpha.5+007'));
}
#[Test]
public function it_can_get_individual_properties(): void
{
$version = new SemVer\Version('v1.3.37-alpha.5+007');
$this->assertEquals(1, $version->major);
$this->assertEquals(3, $version->minor);
$this->assertEquals(37, $version->patch);
$this->assertEquals('alpha.5', $version->preRelease);
$this->assertEquals('007', $version->build);
}
#[Test]
public function it_can_increment_major(): void
{
$version = new SemVer\Version('v1.3.37');
$version->incrementMajor();
$this->assertEquals('2.0.0', (string) $version);
}
#[Test]
public function it_can_set_major(): void
{
$version = new SemVer\Version('v1.3.37');
$version->setMajor(7);
$this->assertEquals('7.0.0', (string) $version);
}
#[Test]
public function it_can_increment_minor(): void
{
$version = new SemVer\Version('v1.3.37');
$version->incrementMinor();
$this->assertEquals('1.4.0', (string) $version);
}
#[Test]
public function it_can_set_minor(): void
{
$version = new SemVer\Version('v1.3.37');
$version->setMinor(5);
$this->assertEquals('1.5.0', (string) $version);
}
#[Test]
public function it_can_increment_patch(): void
{
$version = new SemVer\Version('v1.3.37');
$version->incrementPatch();
$this->assertEquals('1.3.38', (string) $version);
}
#[Test]
public function it_can_increment_prerelease(): void
{
$version = new SemVer\Version('v1.3.37');
$version->setPreRelease('alpha.5');
$version->incrementPreRelease();
$this->assertEquals('1.3.37-alpha.6', (string) $version);
}
#[Test]
public function it_can_increment_prerelease_without_number(): void
{
$version = new SemVer\Version('v1.3.37');
$version->setPreRelease('alpha');
$version->incrementPreRelease();
$this->assertEquals('1.3.37-alpha.1', (string) $version);
}
#[Test]
public function it_can_increment_prerelease_without_prefix_for_prerelease(): void
{
$version = new SemVer\Version('v1.3.37');
$version->setPreRelease('5');
$version->incrementPreRelease();
$this->assertEquals('1.3.37-6', (string) $version);
}
#[Test]
public function it_can_increment_prerelease_containing_multiple_dots(): void
{
$version = new SemVer\Version('v1.3.37');
$version->setPreRelease('alpha.a.b.5');
$version->incrementPreRelease();
$this->assertEquals('1.3.37-alpha.a.b.6', (string) $version);
}
#[Test]
public function it_can_increment_prerelease_containing_multiple_dots_and_without_number(): void
{
$version = new SemVer\Version('v1.3.37');
$version->setPreRelease('alpha.a.b');
$version->incrementPreRelease();
$this->assertEquals('1.3.37-alpha.a.b.1', (string) $version);
}
#[Test]
public function it_can_increment_prerelease_and_patch_when_prerelease_is_null(): void
{
$version = new SemVer\Version('v1.3.37');
$version->incrementPreRelease();
$this->assertEquals('1.3.38-1', (string) $version);
}
#[Test]
public function it_can_set_patch(): void
{
$version = new SemVer\Version('v1.3.37');
$version->setPatch(12);
$this->assertEquals('1.3.12', (string) $version);
}
#[Test]
public function it_can_set_pre_release(): void
{
$version = new SemVer\Version('v1.3.37');
$version->setPreRelease('alpha.5');
$this->assertEquals('1.3.37-alpha.5', (string) $version);
}
#[Test]
public function it_can_unset_pre_release(): void
{
$version = (new SemVer\Version('v1.3.37-alpha.5'))->setPreRelease(null);
$this->assertNull($version->preRelease);
}
#[Test]
public function it_can_set_build(): void
{
$version = new SemVer\Version('v1.3.37');
$version->setBuild('007');
$this->assertEquals('1.3.37+007', (string) $version);
}
#[Test]
public function it_can_unset_build(): void
{
$version = (new SemVer\Version('v1.3.37+007'))->setBuild(null);
$this->assertNull($version->build);
}
#[Test]
public function it_can_be_greater_than_another_semver_object(): void
{
$version = new SemVer\Version('v1.3.37');
$this->assertTrue($version->gt(new SemVer\Version('v0.5.0')));
$this->assertTrue($version->gt(new SemVer\Version('v1.3.36')));
$this->assertFalse($version->gt(new SemVer\Version('v1.3.38')));
$this->assertFalse($version->gt(new SemVer\Version('v1.3.37')));
}
#[Test]
public function it_can_be_less_than_another_semver_object(): void
{
$version = new SemVer\Version('v1.3.37');
$this->assertTrue($version->lt(new SemVer\Version('v1.3.38')));
$this->assertTrue($version->lt(new SemVer\Version('v1.4.0')));
$this->assertFalse($version->lt(new SemVer\Version('v1.3.36')));
$this->assertFalse($version->lt(new SemVer\Version('v1.3.37')));
}
#[Test]
public function it_can_be_equal_to_another_semver_object(): void
{
$version = new SemVer\Version('v1.3.37');
$this->assertTrue($version->eq(new SemVer\Version('v1.3.37')));
$this->assertFalse($version->eq(new SemVer\Version('v1.2.3')));
}
#[Test]
public function it_can_be_not_equal_to_another_semver_object(): void
{
$version = new SemVer\Version('v1.3.37');
$this->assertTrue($version->neq(new SemVer\Version('v1.2.3')));
$this->assertFalse($version->neq(new SemVer\Version('v1.3.37')));
}
#[Test]
public function it_can_be_greater_than_or_equal_to_another_semver_object(): void
{
$version = new SemVer\Version('v1.3.37');
$this->assertTrue($version->gte(new SemVer\Version('v1.2.3')));
$this->assertTrue($version->gte(new SemVer\Version('v1.3.37')));
$this->assertFalse($version->gte(new SemVer\Version('v2.3.4')));
}
#[Test]
public function it_can_be_less_than_or_equal_to_another_semver_object(): void
{
$version = new SemVer\Version('v1.3.37');
$this->assertTrue($version->lte(new SemVer\Version('v2.3.4')));
$this->assertTrue($version->lte(new SemVer\Version('v1.3.37')));
$this->assertFalse($version->lte(new SemVer\Version('v1.2.3')));
}
#[Test]
public function it_can_be_greater_than_another_semver_object_using_major(): void
{
$version = new SemVer\Version('v2.3.37');
$this->assertTrue($version->gt(new SemVer\Version('v0.5.0'), Compare::MAJOR));
$this->assertTrue($version->gt(new SemVer\Version('v1.3.38'), Compare::MAJOR));
$this->assertFalse($version->gt(new SemVer\Version('v2.3.36'), Compare::MAJOR));
$this->assertFalse($version->gt(new SemVer\Version('v3.3.36'), Compare::MAJOR));
}
#[Test]
public function it_can_be_less_than_another_semver_object_using_major(): void
{
$version = new SemVer\Version('v2.3.37');
$this->assertTrue($version->lt(new SemVer\Version('v3.3.38'), Compare::MAJOR));
$this->assertFalse($version->lt(new SemVer\Version('v2.3.36'), Compare::MAJOR));
$this->assertFalse($version->lt(new SemVer\Version('v1.3.37'), Compare::MAJOR));
}
#[Test]
public function it_can_be_equal_to_another_semver_object_using_major(): void
{
$version = new SemVer\Version('v1.3.37-alpha.5');
$this->assertTrue($version->eq(new SemVer\Version('v1.3.37-alpha.4'), Compare::MAJOR));
$this->assertTrue($version->eq(new SemVer\Version('v1.2.3'), Compare::MAJOR));
}
#[Test]
public function it_can_be_not_equal_to_another_semver_object_using_major(): void
{
$version = new SemVer\Version('v2.3.37');
$this->assertTrue($version->neq(new SemVer\Version('v3.2.3'), Compare::MAJOR));
$this->assertFalse($version->neq(new SemVer\Version('v2.2.3'), Compare::MAJOR));
$this->assertTrue($version->neq(new SemVer\Version('v1.3.37'), Compare::MAJOR));
}
#[Test]
public function it_can_be_greater_than_or_equal_to_another_semver_object_using_major(): void
{
$version = new SemVer\Version('v3.3.37-alpha.5');
$this->assertTrue($version->gte(new SemVer\Version('v1.3.4'), Compare::MAJOR));
$this->assertTrue($version->gte(new SemVer\Version('v2.3.37-alpha.6'), Compare::MAJOR));
$this->assertTrue($version->gte(new SemVer\Version('v3.2.3'), Compare::MAJOR));
$this->assertFalse($version->gte(new SemVer\Version('v4.2.3'), Compare::MAJOR));
}
#[Test]
public function it_can_be_less_than_or_equal_to_another_semver_object_using_major(): void
{
$version = new SemVer\Version('v2.3.37-alpha.5');
$this->assertTrue($version->lte(new SemVer\Version('v3.2.3'), Compare::MAJOR));
$this->assertTrue($version->lte(new SemVer\Version('v2.3.37-alpha.4'), Compare::MAJOR));
$this->assertFalse($version->lte(new SemVer\Version('v1.3.4'), Compare::MAJOR));
}
#[Test]
public function it_can_be_greater_than_another_semver_object_using_minor(): void
{
$version = new SemVer\Version('v1.3.37-alpha.5');
$this->assertTrue($version->gt(new SemVer\Version('v0.5.0'), Compare::MINOR));
$this->assertTrue($version->gt(new SemVer\Version('v1.2.40'), Compare::MINOR));
$this->assertFalse($version->gt(new SemVer\Version('v1.3.38-alpha.5'), Compare::MINOR));
$this->assertFalse($version->gt(new SemVer\Version('v1.4.0'), Compare::MINOR));
}
#[Test]
public function it_can_be_less_than_another_semver_object_using_minor(): void
{
$version = new SemVer\Version('v1.3.37-alpha.5');
$this->assertTrue($version->lt(new SemVer\Version('v1.4.38'), Compare::MINOR));
$this->assertTrue($version->lt(new SemVer\Version('v1.4.0'), Compare::MINOR));
$this->assertFalse($version->lt(new SemVer\Version('v1.2.36'), Compare::MINOR));
$this->assertFalse($version->lt(new SemVer\Version('v1.3.37-alpha.6'), Compare::MINOR));
}
#[Test]
public function it_can_be_equal_to_another_semver_object_using_minor(): void
{
$version = new SemVer\Version('v1.3.37-alpha.5');
$this->assertFalse($version->eq(new SemVer\Version('v1.4.3'), Compare::MINOR));
$this->assertTrue($version->eq(new SemVer\Version('v1.3.37-alpha.4'), Compare::MINOR));
$this->assertFalse($version->eq(new SemVer\Version('v1.2.3'), Compare::MINOR));
}
#[Test]
public function it_can_be_not_equal_to_another_semver_object_using_minor(): void
{
$version = new SemVer\Version('v1.3.37-alpha.5');
$this->assertTrue($version->neq(new SemVer\Version('v1.2.37-alpha.5'), Compare::MINOR));
$this->assertFalse($version->neq(new SemVer\Version('v1.3.37-alpha.6'), Compare::MINOR));
$this->assertTrue($version->neq(new SemVer\Version('v1.4.37'), Compare::MINOR));
}
#[Test]
public function it_can_be_greater_than_or_equal_to_another_semver_object_using_minor(): void
{
$version = new SemVer\Version('v1.3.37-alpha.5');
$this->assertTrue($version->gte(new SemVer\Version('v1.3.38-alpha.4'), Compare::MINOR));
$this->assertTrue($version->gte(new SemVer\Version('v1.2.3'), Compare::MINOR));
$this->assertFalse($version->gte(new SemVer\Version('v1.4.4'), Compare::MINOR));
$this->assertFalse($version->gte(new SemVer\Version('v2.3.4'), Compare::MINOR));
}
#[Test]
public function it_can_be_less_than_or_equal_to_another_semver_object_using_minor(): void
{
$version = new SemVer\Version('v1.3.37-alpha.5');
$this->assertTrue($version->lte(new SemVer\Version('v2.3.4'), Compare::MINOR));
$this->assertTrue($version->lte(new SemVer\Version('v1.3.37'), Compare::MINOR));
$this->assertTrue($version->lte(new SemVer\Version('v1.3.36'), Compare::MINOR));
$this->assertFalse($version->lte(new SemVer\Version('v1.2.37-alpha.5'), Compare::MINOR));
}
#[Test]
public function it_can_be_greater_than_another_semver_object_using_patch(): void
{
$version = new SemVer\Version('v1.3.37-alpha.5');
$this->assertTrue($version->gt(new SemVer\Version('v0.5.0'), Compare::PATCH));
$this->assertTrue($version->gt(new SemVer\Version('v1.3.36'), Compare::PATCH));
$this->assertFalse($version->gt(new SemVer\Version('v1.3.38'), Compare::PATCH));
$this->assertFalse($version->gt(new SemVer\Version('v1.3.37-alpha.4'), Compare::PATCH));
}
#[Test]
public function it_can_be_less_than_another_semver_object_using_patch(): void
{
$version = new SemVer\Version('v1.3.37-alpha.5');
$this->assertTrue($version->lt(new SemVer\Version('v1.3.38'), Compare::PATCH));
$this->assertTrue($version->lt(new SemVer\Version('v1.4.0'), Compare::PATCH));
$this->assertFalse($version->lt(new SemVer\Version('v1.3.36'), Compare::PATCH));
$this->assertFalse($version->lt(new SemVer\Version('v1.3.37-alpha.6'), Compare::PATCH));
}
#[Test]
public function it_can_be_equal_to_another_semver_object_using_patch(): void
{
$version = new SemVer\Version('v1.3.37-alpha.5');
$this->assertTrue($version->eq(new SemVer\Version('v1.3.37-alpha.6'), Compare::PATCH));
$this->assertFalse($version->eq(new SemVer\Version('v1.2.3'), Compare::PATCH));
}
#[Test]
public function it_can_be_not_equal_to_another_semver_object_using_patch(): void
{
$version = new SemVer\Version('v1.3.37-alpha.5');
$this->assertTrue($version->neq(new SemVer\Version('v1.2.3'), Compare::PATCH));
$this->assertFalse($version->neq(new SemVer\Version('v1.3.37-alpha.6'), Compare::PATCH));
}
#[Test]
public function it_can_be_greater_than_or_equal_to_another_semver_object_using_patch(): void
{
$version = new SemVer\Version('v1.3.37-alpha.5');
$this->assertTrue($version->gte(new SemVer\Version('v1.2.3'), Compare::PATCH));
$this->assertTrue($version->gte(new SemVer\Version('v1.3.37-alpha.6'), Compare::PATCH));
$this->assertFalse($version->gte(new SemVer\Version('v2.3.4'), Compare::PATCH));
}
#[Test]
public function it_can_be_less_than_or_equal_to_another_semver_object_using_patch(): void
{
$version = new SemVer\Version('v1.3.37-alpha.5');
$this->assertTrue($version->lte(new SemVer\Version('v2.3.4'), Compare::PATCH));
$this->assertTrue($version->lte(new SemVer\Version('v1.3.37-alpha.4'), Compare::PATCH));
$this->assertFalse($version->lte(new SemVer\Version('v1.2.3'), Compare::PATCH));
}
#[Test]
public function setting_the_major_version_resets_appropriate_properties(): void
{
$version = new SemVer\Version('v1.3.37-alpha.5+007');
$version->setMajor(2);
$this->assertEquals(2, $version->major);
$this->assertEquals(0, $version->minor);
$this->assertEquals(0, $version->patch);
$this->assertNull($version->preRelease);
$this->assertNull($version->build);
}
#[Test]
public function setting_the_minor_version_resets_appropriate_properties(): void
{
$version = new SemVer\Version('v1.3.37-alpha.5+007');
$version->setMinor(4);
$this->assertEquals(1, $version->major);
$this->assertEquals(4, $version->minor);
$this->assertEquals(0, $version->patch);
$this->assertNull($version->preRelease);
$this->assertNull($version->build);
}
#[Test]
public function setting_the_patch_version_resets_appropriate_properties(): void
{
$version = new SemVer\Version('v1.3.37-alpha.5+007');
$version->setPatch(38);
$this->assertEquals(1, $version->major);
$this->assertEquals(3, $version->minor);
$this->assertEquals(38, $version->patch);
$this->assertNull($version->preRelease);
$this->assertNull($version->build);
}
#[Test]
public function it_compares_pre_release_tags(): void
{
$alpha = new SemVer\Version('v1.3.37-alpha');
$beta = new SemVer\Version('v1.3.37-beta');
$this->assertTrue($alpha->lt($beta));
$this->assertFalse($alpha->gt($beta));
$this->assertTrue($alpha->lte($beta));
$this->assertFalse($alpha->gte($beta));
$this->assertFalse($alpha->eq($beta));
}
#[Test]
public function it_ignores_the_build_version_when_comparing_versions(): void
{
$oldBuild = new SemVer\Version('v1.3.37-alpha.5+006');
$newBuild = new SemVer\Version('v1.3.37-alpha.5+007');
$this->assertTrue($oldBuild->eq($newBuild));
$this->assertFalse($oldBuild->neq($newBuild));
$this->assertFalse($oldBuild->gt($newBuild));
$this->assertFalse($oldBuild->lt($newBuild));
$this->assertTrue($oldBuild->gte($newBuild));
$this->assertTrue($oldBuild->lte($newBuild));
$this->assertTrue((new SemVer\Version('v1.3.37'))->eq(new SemVer\Version('v1.3.37+007')));
}
#[Test]
#[\PHPUnit\Framework\Attributes\DataProvider('pre_release_comparison_provider')]
public function it_compares_pre_release_tags_vs_release(string $release, string $prerelease): void
{
$release = new SemVer\Version($release);
$prerelease = new SemVer\Version($prerelease);
$this->assertFalse($release->eq($prerelease));
$this->assertFalse($release->lt($prerelease));
$this->assertFalse($release->lte($prerelease));
$this->assertTrue($release->gt($prerelease));
$this->assertTrue($release->gte($prerelease));
$this->assertFalse($prerelease->gt($release));
$this->assertFalse($prerelease->eq($release));
$this->assertFalse($prerelease->gte($release));
$this->assertTrue($prerelease->lt($release));
$this->assertTrue($prerelease->lte($release));
}
#[Test]
public function it_can_compare_two_versions(): void
{
$version1 = new SemVer\Version('v1.3.37');
$version2 = new SemVer\Version('v3.2.1');
// Major Comparisons
$this->assertEquals(-1, SemVer\Version::compare(new SemVer\Version('v1.2.3'), new SemVer\Version('v3.2.1')));
$this->assertEquals(0, SemVer\Version::compare(new SemVer\Version('v1.2.3'), new SemVer\Version('v1.2.3')));
$this->assertEquals(1, SemVer\Version::compare(new SemVer\Version('v3.2.1'), new SemVer\Version('v1.2.3')));
// Minor Comparisons
$this->assertEquals(-1, SemVer\Version::compare(new SemVer\Version('v0.1.2'), new SemVer\Version('v0.2.1')));
$this->assertEquals(0, SemVer\Version::compare(new SemVer\Version('v0.1.2'), new SemVer\Version('v0.1.2')));
$this->assertEquals(1, SemVer\Version::compare(new SemVer\Version('v0.2.1'), new SemVer\Version('v0.1.2')));
// Patch Comparisons
$this->assertEquals(-1, SemVer\Version::compare(new SemVer\Version('v1.0.1'), new SemVer\Version('v1.0.2')));
$this->assertEquals(0, SemVer\Version::compare(new SemVer\Version('v1.0.0'), new SemVer\Version('v1.0.0')));
$this->assertEquals(1, SemVer\Version::compare(new SemVer\Version('v1.0.2'), new SemVer\Version('v1.0.1')));
}
#[Test]
public function it_can_be_serialized_to_json(): void
{
$version = new SemVer\Version('v1.3.37');
$this->assertInstanceOf(JsonSerializable::class, $version);
$this->assertEquals('1.3.37', $version->jsonSerialize());
}
#[Test]
public function it_can_determine_if_it_is_a_pre_release(): void
{
$version = new SemVer\Version('v1.3.37-alpha.5+007');
$this->assertTrue($version->isPreRelease());
}
#[Test]
public function can_determine_if_it_is_not_a_pre_release(): void
{
$version = new SemVer\Version('v1.3.37+007');
$this->assertFalse($version->isPreRelease());
}
#[Test]
public function can_determine_if_it_has_a_build_string(): void
{
$version = new SemVer\Version('v1.3.37-alpha.5+007');
$this->assertTrue($version->hasBuild());
}
#[Test]
public function it_can_determine_if_it_has_a_build_string(): void
{
$version = new SemVer\Version('v1.3.37-alpha');
$this->assertFalse($version->hasBuild());
}
}
gitextract_fljnwk0f/
├── .editorconfig
├── .gitattributes
├── .github/
│ ├── FUNDING.yml
│ ├── dependabot.yml
│ └── workflows/
│ └── test-suite.yaml
├── .gitignore
├── .php-cs-fixer.dist.php
├── LICENSE
├── Makefile
├── README.md
├── composer.json
├── phpstan-ignores.neon
├── phpstan.neon.dist
├── phpunit.xml
├── src/
│ ├── Enums/
│ │ └── Compare.php
│ ├── Exceptions/
│ │ └── InvalidVersionException.php
│ ├── Support/
│ │ └── helpers.php
│ ├── Traits/
│ │ ├── Comparable.php
│ │ └── Incrementable.php
│ └── Version.php
└── tests/
└── VersionTest.php
SYMBOL INDEX (93 symbols across 6 files)
FILE: src/Exceptions/InvalidVersionException.php
class InvalidVersionException (line 7) | class InvalidVersionException extends Exception {}
FILE: src/Support/helpers.php
function semver (line 11) | function semver(string $string): Version
FILE: src/Traits/Comparable.php
type Comparable (line 8) | trait Comparable
method compare (line 17) | public static function compare(Version $version1, Version $version2, C...
method gt (line 56) | public function gt(Version $version, Compare $comparison = Compare::FU...
method lt (line 69) | public function lt(Version $version, Compare $comparison = Compare::FU...
method eq (line 82) | public function eq(Version $version, Compare $comparison = Compare::FU...
method neq (line 95) | public function neq(Version $version, Compare $comparison = Compare::F...
method gte (line 108) | public function gte(Version $version, Compare $comparison = Compare::F...
method lte (line 121) | public function lte(Version $version, Compare $comparison = Compare::F...
FILE: src/Traits/Incrementable.php
type Incrementable (line 5) | trait Incrementable
method incrementMajor (line 12) | public function incrementMajor(): static
method incrementMinor (line 24) | public function incrementMinor(): static
method incrementPatch (line 36) | public function incrementPatch(): static
method incrementPreRelease (line 48) | public function incrementPreRelease(): static
FILE: src/Version.php
class Version (line 17) | class Version implements JsonSerializable
method __construct (line 44) | final public function __construct(string $version = '0.1.0')
method __get (line 56) | public function __get(string $property)
method __toString (line 66) | public function __toString(): string
method parse (line 92) | public static function parse(string $version): static
method jsonSerialize (line 114) | public function jsonSerialize(): mixed
method setVersion (line 128) | public function setVersion(string $version): static
method setMajor (line 152) | public function setMajor(int $value): static
method setMinor (line 167) | public function setMinor(int $value): static
method setPatch (line 182) | public function setPatch(int $value): static
method setPreRelease (line 198) | public function setPreRelease($value): static
method setBuild (line 212) | public function setBuild($value): static
method prefix (line 227) | public function prefix(string $prefix = 'v'): string
method isPreRelease (line 237) | public function isPreRelease(): bool
method hasBuild (line 247) | public function hasBuild(): bool
FILE: tests/VersionTest.php
class VersionTest (line 17) | #[CoversClass(Version::class)]
method pre_release_comparison_provider (line 23) | public static function pre_release_comparison_provider(): array
method it_can_be_initialized (line 41) | #[Test]
method it_can_be_initialized_with_the_helper_function (line 49) | #[Test]
method it_throws_a_runtime_exception_for_an_invalid_version (line 57) | #[Test]
method it_can_parse_an_incomplete_version_string (line 65) | #[Test]
method it_throws_a_runtime_exception_when_parsing_an_invalid_version (line 79) | #[Test]
method it_can_set_and_retrieve_a_version (line 87) | #[Test]
method it_can_return_a_prefixed_version_string (line 96) | #[Test]
method it_can_be_cast_to_a_string (line 105) | #[Test]
method it_can_get_individual_properties (line 114) | #[Test]
method it_can_increment_major (line 126) | #[Test]
method it_can_set_major (line 135) | #[Test]
method it_can_increment_minor (line 144) | #[Test]
method it_can_set_minor (line 153) | #[Test]
method it_can_increment_patch (line 162) | #[Test]
method it_can_increment_prerelease (line 171) | #[Test]
method it_can_increment_prerelease_without_number (line 181) | #[Test]
method it_can_increment_prerelease_without_prefix_for_prerelease (line 191) | #[Test]
method it_can_increment_prerelease_containing_multiple_dots (line 201) | #[Test]
method it_can_increment_prerelease_containing_multiple_dots_and_without_number (line 211) | #[Test]
method it_can_increment_prerelease_and_patch_when_prerelease_is_null (line 221) | #[Test]
method it_can_set_patch (line 230) | #[Test]
method it_can_set_pre_release (line 239) | #[Test]
method it_can_unset_pre_release (line 248) | #[Test]
method it_can_set_build (line 256) | #[Test]
method it_can_unset_build (line 265) | #[Test]
method it_can_be_greater_than_another_semver_object (line 273) | #[Test]
method it_can_be_less_than_another_semver_object (line 284) | #[Test]
method it_can_be_equal_to_another_semver_object (line 295) | #[Test]
method it_can_be_not_equal_to_another_semver_object (line 304) | #[Test]
method it_can_be_greater_than_or_equal_to_another_semver_object (line 313) | #[Test]
method it_can_be_less_than_or_equal_to_another_semver_object (line 323) | #[Test]
method it_can_be_greater_than_another_semver_object_using_major (line 333) | #[Test]
method it_can_be_less_than_another_semver_object_using_major (line 344) | #[Test]
method it_can_be_equal_to_another_semver_object_using_major (line 354) | #[Test]
method it_can_be_not_equal_to_another_semver_object_using_major (line 363) | #[Test]
method it_can_be_greater_than_or_equal_to_another_semver_object_using_major (line 373) | #[Test]
method it_can_be_less_than_or_equal_to_another_semver_object_using_major (line 384) | #[Test]
method it_can_be_greater_than_another_semver_object_using_minor (line 394) | #[Test]
method it_can_be_less_than_another_semver_object_using_minor (line 405) | #[Test]
method it_can_be_equal_to_another_semver_object_using_minor (line 416) | #[Test]
method it_can_be_not_equal_to_another_semver_object_using_minor (line 426) | #[Test]
method it_can_be_greater_than_or_equal_to_another_semver_object_using_minor (line 436) | #[Test]
method it_can_be_less_than_or_equal_to_another_semver_object_using_minor (line 447) | #[Test]
method it_can_be_greater_than_another_semver_object_using_patch (line 458) | #[Test]
method it_can_be_less_than_another_semver_object_using_patch (line 469) | #[Test]
method it_can_be_equal_to_another_semver_object_using_patch (line 480) | #[Test]
method it_can_be_not_equal_to_another_semver_object_using_patch (line 489) | #[Test]
method it_can_be_greater_than_or_equal_to_another_semver_object_using_patch (line 498) | #[Test]
method it_can_be_less_than_or_equal_to_another_semver_object_using_patch (line 508) | #[Test]
method setting_the_major_version_resets_appropriate_properties (line 518) | #[Test]
method setting_the_minor_version_resets_appropriate_properties (line 531) | #[Test]
method setting_the_patch_version_resets_appropriate_properties (line 544) | #[Test]
method it_compares_pre_release_tags (line 557) | #[Test]
method it_ignores_the_build_version_when_comparing_versions (line 570) | #[Test]
method it_compares_pre_release_tags_vs_release (line 586) | #[Test]
method it_can_compare_two_versions (line 606) | #[Test]
method it_can_be_serialized_to_json (line 628) | #[Test]
method it_can_determine_if_it_is_a_pre_release (line 637) | #[Test]
method can_determine_if_it_is_not_a_pre_release (line 645) | #[Test]
method can_determine_if_it_has_a_build_string (line 653) | #[Test]
method it_can_determine_if_it_has_a_build_string (line 661) | #[Test]
Condensed preview — 21 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (53K chars).
[
{
"path": ".editorconfig",
"chars": 305,
"preview": "root = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\nindent_size = 4\nindent_style = space\ninsert_final_newline = true\ntrim_"
},
{
"path": ".gitattributes",
"chars": 180,
"preview": "tests export-ignore\n.gitattributes export-ignore\n.gitignore export-ignore\n.php_cs.dist export-ignore\n"
},
{
"path": ".github/FUNDING.yml",
"chars": 71,
"preview": "github: PHLAK\npatreon: PHLAK\ncustom: https://paypal.me/ChrisKankiewicz\n"
},
{
"path": ".github/dependabot.yml",
"chars": 349,
"preview": "version: 2\n\nupdates:\n - package-ecosystem: composer\n directory: \"/\"\n schedule:\n interval: monthly\n time"
},
{
"path": ".github/workflows/test-suite.yaml",
"chars": 1645,
"preview": "name: SemVer Test Suite\non: [push, pull_request, workflow_dispatch]\n\njobs:\n coding-standards:\n name: Coding Standard"
},
{
"path": ".gitignore",
"chars": 61,
"preview": "/.php-cs-fixer.cache\n/.phpunit.cache\n/composer.lock\n/vendor/\n"
},
{
"path": ".php-cs-fixer.dist.php",
"chars": 246,
"preview": "<?php\n\nrequire __DIR__ . '/vendor/autoload.php';\n\n$finder = PhpCsFixer\\Finder::create()->in([\n __DIR__ . DIRECTORY_SE"
},
{
"path": "LICENSE",
"chars": 1101,
"preview": "MIT License\n\nCopyright (c) 2024 Chris Kankiewicz <Chris@ChrisKankiewicz.com>\n\nPermission is hereby granted, free of char"
},
{
"path": "Makefile",
"chars": 502,
"preview": "dev development: # Build application for development\n\t@composer install --no-interaction\n\nprod production: # Build appli"
},
{
"path": "README.md",
"chars": 5991,
"preview": "SemVer\n======\n\n<p align=\"center\">\n <img src=\"semver.png\" alt=\"SemVer\" width=\"50%\">\n</p>\n\n<p align=\"center\">\n <a href"
},
{
"path": "composer.json",
"chars": 1229,
"preview": "{\n \"name\": \"phlak/semver\",\n \"description\": \"Semantic versioning helper library\",\n \"type\": \"library\",\n \"licen"
},
{
"path": "phpstan-ignores.neon",
"chars": 153,
"preview": "parameters:\n ignoreErrors:\n - message: \"/^Method .+ throws checked exception .+ but it's missing from the PHPDoc @th"
},
{
"path": "phpstan.neon.dist",
"chars": 348,
"preview": "parameters:\n\n paths:\n - src\n - tests\n\n level: max\n\n checkFunctionNameCase: true\n\n exceptions:\n implicitThro"
},
{
"path": "phpunit.xml",
"chars": 475,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit bootstrap=\"vendor/autoload.php\" colors=\"true\"\n xmlns:xsi=\"http://www."
},
{
"path": "src/Enums/Compare.php",
"chars": 118,
"preview": "<?php\n\nnamespace PHLAK\\SemVer\\Enums;\n\nenum Compare\n{\n case FULL;\n case MAJOR;\n case MINOR;\n case PATCH;\n}\n"
},
{
"path": "src/Exceptions/InvalidVersionException.php",
"chars": 110,
"preview": "<?php\n\nnamespace PHLAK\\SemVer\\Exceptions;\n\nuse Exception;\n\nclass InvalidVersionException extends Exception {}\n"
},
{
"path": "src/Support/helpers.php",
"chars": 304,
"preview": "<?php\n\nuse PHLAK\\SemVer\\Version;\n\nif (! function_exists('semver')) {\n /**\n * Create a SemVer version object.\n "
},
{
"path": "src/Traits/Comparable.php",
"chars": 4318,
"preview": "<?php\n\nnamespace PHLAK\\SemVer\\Traits;\n\nuse PHLAK\\SemVer\\Enums\\Compare;\nuse PHLAK\\SemVer\\Version;\n\ntrait Comparable\n{\n "
},
{
"path": "src/Traits/Incrementable.php",
"chars": 1491,
"preview": "<?php\n\nnamespace PHLAK\\SemVer\\Traits;\n\ntrait Incrementable\n{\n /**\n * Increment the major version value by one.\n "
},
{
"path": "src/Version.php",
"chars": 6480,
"preview": "<?php\n\nnamespace PHLAK\\SemVer;\n\nuse JsonSerializable;\nuse PHLAK\\SemVer\\Exceptions\\InvalidVersionException;\nuse PHLAK\\Sem"
},
{
"path": "tests/VersionTest.php",
"chars": 24599,
"preview": "<?php\n\nnamespace PHLAK\\SemVer\\Tests;\n\nuse JsonSerializable;\nuse PHLAK\\SemVer;\nuse PHLAK\\SemVer\\Enums\\Compare;\nuse PHLAK\\"
}
]
About this extraction
This page contains the full source code of the PHLAK/SemVer GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 21 files (48.9 KB), approximately 14.7k tokens, and a symbol index with 93 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.