├── .editorconfig ├── .github ├── FUNDING.yml ├── dependabot.yml └── workflows │ └── test-suite.yaml ├── .php-cs-fixer.dist.php ├── LICENSE ├── Makefile ├── README.md ├── composer.json ├── phpstan-ignores.neon ├── phpstan.neon.dist ├── semver.png └── src ├── Enums └── Compare.php ├── Exceptions └── InvalidVersionException.php ├── Support └── helpers.php ├── Traits ├── Comparable.php └── Incrementable.php └── Version.php /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 4 7 | indent_style = space 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.json] 12 | indent_style = space 13 | indent_size = 4 14 | 15 | [*.md] 16 | trim_trailing_whitespace = false 17 | indent_size = 4 18 | 19 | [*.{yml,yaml}] 20 | indent_size = 2 21 | indent_style = space 22 | 23 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: PHLAK 2 | patreon: PHLAK 3 | custom: https://paypal.me/ChrisKankiewicz 4 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | updates: 4 | - package-ecosystem: composer 5 | directory: "/" 6 | schedule: 7 | interval: monthly 8 | timezone: US/Arizona 9 | open-pull-requests-limit: 10 10 | assignees: 11 | - PHLAK 12 | 13 | - package-ecosystem: github-actions 14 | directory: "/" 15 | schedule: 16 | interval: monthly 17 | timezone: US/Arizona 18 | assignees: 19 | - PHLAK 20 | -------------------------------------------------------------------------------- /.github/workflows/test-suite.yaml: -------------------------------------------------------------------------------- 1 | name: SemVer Test Suite 2 | on: [push, pull_request, workflow_dispatch] 3 | 4 | jobs: 5 | coding-standards: 6 | name: Coding Standards 7 | runs-on: 'ubuntu-latest' 8 | 9 | env: 10 | PHP_CS_FIXER_IGNORE_ENV: 1 11 | 12 | steps: 13 | - name: Checkout Repository 14 | uses: actions/checkout@v4 15 | 16 | - name: Setup PHP 17 | uses: shivammathur/setup-php@v2 18 | with: 19 | php-version: '8.4' 20 | 21 | - name: Install PHP Dependencies 22 | run: composer install --no-interaction --no-progress --no-scripts --prefer-dist 23 | 24 | - name: Verify Coding Standards 25 | run: vendor/bin/php-cs-fixer fix --diff --dry-run 26 | 27 | static-analysis: 28 | name: Static Analysis 29 | runs-on: 'ubuntu-latest' 30 | 31 | steps: 32 | - name: Checkout Repository 33 | uses: actions/checkout@v4 34 | 35 | - name: Setup PHP 36 | uses: shivammathur/setup-php@v2 37 | with: 38 | php-version: '8.4' 39 | 40 | - name: Install PHP Dependencies 41 | run: composer install --no-interaction --no-progress --no-scripts --prefer-dist 42 | 43 | - name: Run Static Analysis 44 | run: vendor/bin/phpstan analyze 45 | 46 | tests: 47 | name: Tests 48 | runs-on: 'ubuntu-latest' 49 | 50 | strategy: 51 | matrix: 52 | php-versions: ['8.1', '8.2', '8.3', '8.4'] 53 | 54 | steps: 55 | - name: Checkout Repository 56 | uses: actions/checkout@v4 57 | 58 | - name: Setup PHP 59 | uses: shivammathur/setup-php@v2 60 | with: 61 | php-version: ${{ matrix.php-versions }} 62 | coverage: xdebug 63 | 64 | - name: Install PHP Dependencies 65 | run: composer install --no-interaction --no-progress --no-scripts --prefer-dist 66 | 67 | - name: Run Tests 68 | run: vendor/bin/phpunit --coverage-text 69 | -------------------------------------------------------------------------------- /.php-cs-fixer.dist.php: -------------------------------------------------------------------------------- 1 | in([ 6 | __DIR__ . DIRECTORY_SEPARATOR . 'src', 7 | __DIR__ . DIRECTORY_SEPARATOR . 'tests', 8 | ]); 9 | 10 | return PHLAK\CodingStandards\ConfigFactory::make($finder); 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Chris Kankiewicz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | dev development: # Build application for development 2 | @composer install --no-interaction 3 | 4 | prod production: # Build application for production 5 | @composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader 6 | 7 | test: # Run coding standards/static analysis checks and tests 8 | @vendor/bin/php-cs-fixer fix --diff --dry-run \ 9 | && vendor/bin/phpstan analyze \ 10 | && vendor/bin/phpunit --coverage-text 11 | 12 | coverage: # Generate an HTML coverage report 13 | @vendor/bin/phpunit --coverage-html .coverage 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SemVer 2 | ====== 3 | 4 |

5 | SemVer 6 |

7 | 8 |

9 | Semantic versioning helper library 10 | • Created by Chris Kankiewicz (@phlak.dev) 11 |

12 | 13 |

14 | Join our Community 15 | Become a Sponsor 16 | One-time Donation 17 |
18 | Latest Stable Version 19 | Total Downloads 20 | License 21 | Tests Status 22 |

23 | 24 | --- 25 | 26 | Requirements 27 | ------------ 28 | 29 | - [PHP](https://php.net) >= 8.1 30 | 31 | Installation 32 | ------------ 33 | 34 | ```bash 35 | composer require phlak/semver 36 | ``` 37 | 38 | Initializing 39 | ------------ 40 | 41 | ```php 42 | use PHLAK\SemVer; 43 | 44 | $version = new SemVer\Version(); // Initilializes to '0.1.0' 45 | ``` 46 | 47 | Or initialize with a custom version by passing a version string on creation. 48 | Accepts any valid semantic version string with or without a preceding `v`. 49 | 50 | ```php 51 | $version = new SemVer\Version('v1.2.3-alpha.5+sha.8d31ff4'); 52 | ``` 53 | 54 | Or parse an incomple version string with the static `Version::parse()` constructor. 55 | 56 | ```php 57 | $version = SemVer\Version::parse('v1') // Initializes to '1.0.0' 58 | $version = SemVer\Version::parse('v1.2') // Initializes to '1.2.0' 59 | ``` 60 | 61 | Usage 62 | ----- 63 | 64 | #### Retrieve the version or individual values 65 | 66 | ```php 67 | $version = new SemVer\Version('v1.2.3-beta.4+007'); 68 | 69 | echo $version; // '1.2.3-beta.4+007' 70 | echo $version->major; // 1 71 | echo $version->minor; // 2 72 | echo $version->patch; // 3 73 | echo $version->preRelease; // 'beta.4' 74 | echo $version->build; // '007' 75 | ``` 76 | 77 | #### Increment the version 78 | 79 | ```php 80 | $version = new SemVer\Version('v1.2.3'); 81 | 82 | $version->incrementMajor(); // v1.2.3 -> v2.0.0 83 | $version->incrementMinor(); // v1.2.3 -> v1.3.0 84 | $version->incrementPatch(); // v1.2.3 -> v1.2.4 85 | $version->incrementPreRelease(); // v1.2.3-alpha.5 -> v1.2.3-alpha.6 86 | ``` 87 | 88 | #### Set (override) the version or individual values 89 | 90 | ```php 91 | $version = new SemVer\Version(); 92 | 93 | $version->setVersion('v1.2.3'); // v1.2.3 94 | $version->setMajor(3); // v1.2.3 -> v3.0.0 95 | $version->setMinor(5); // v1.2.3 -> v1.5.0 96 | $version->setPatch(7); // v1.2.3 -> 1.2.7 97 | $version->setPreRelease('rc.2'); // v1.2.3 -> v1.2.3-rc.2 98 | $version->setBuild('007'); // v1.2.3 -> v1.2.3+007 99 | ``` 100 | 101 | #### Clear pre-release / build values 102 | 103 | ```php 104 | $version->setPreRelease(null); // v1.2.3-rc.2 -> v1.2.3 105 | $version->setBuild(null); // v1.2.3+007 -> v1.2.3 106 | ``` 107 | 108 | 109 | #### Check for pre-release / build values 110 | 111 | ```php 112 | $version->isPreRelease(); 113 | $version->hasBuild(); 114 | ``` 115 | 116 | #### Compare two SemVer objects 117 | 118 | ```php 119 | $version1 = new SemVer\Version('v1.2.3'); 120 | $version2 = new SemVer\Version('v3.2.1'); 121 | 122 | $version1->gt($version2); // false 123 | $version1->lt($version2); // true 124 | $version1->eq($version2); // false 125 | $version1->neq($version2); // true 126 | $version1->gte($version2); // false 127 | $version1->lte($version2); // true 128 | ``` 129 | 130 | ##### Limit comparison to the major version only 131 | 132 | Ignores the minor, patch and pre-release versions completely 133 | 134 | ```php 135 | $version1 = new SemVer\Version('v1.2.3-alpha.4'); 136 | $version2 = new SemVer\Version('v1.3.4-alpha.5'); 137 | 138 | $version1->gt($version2, Compare::MAJOR); // false 139 | $version1->lt($version2, Compare::MAJOR); // false 140 | $version1->eq($version2, Compare::MAJOR); // true 141 | $version1->neq($version2, Compare::MAJOR); // false 142 | $version1->gte($version2, Compare::MAJOR); // true 143 | $version1->lte($version2, Compare::MAJOR); // true 144 | ``` 145 | 146 | ##### Limit comparison to the major and minor versions only 147 | 148 | Ignores the patch and pre-release versions completely 149 | 150 | ```php 151 | $version1 = new SemVer\Version('v1.2.3-alpha.4'); 152 | $version2 = new SemVer\Version('v1.2.4-alpha.5'); 153 | 154 | $version1->gt($version2, Compare::MINOR); // false 155 | $version1->lt($version2, Compare::MINOR); // false 156 | $version1->eq($version2, Compare::MINOR); // true 157 | $version1->neq($version2, Compare::MINOR); // false 158 | $version1->gte($version2, Compare::MINOR); // true 159 | $version1->lte($version2, Compare::MINOR); // true 160 | ``` 161 | 162 | ##### Limit comparison to the major, minor and patch versions only 163 | 164 | Ignores the pre-release version completely 165 | 166 | ```php 167 | $version1 = new SemVer\Version('v1.2.3-alpha.4'); 168 | $version2 = new SemVer\Version('v1.2.3-alpha.5'); 169 | 170 | $version1->gt($version2, Compare::PATCH); // false 171 | $version1->lt($version2, Compare::PATCH); // false 172 | $version1->eq($version2, Compare::PATCH); // true 173 | $version1->neq($version2, Compare::PATCH); // false 174 | $version1->gte($version2, Compare::PATCH); // true 175 | $version1->lte($version2, Compare::PATCH); // true 176 | ``` 177 | 178 | Troubleshooting 179 | --------------- 180 | 181 | 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). 182 | 183 | Please report bugs to the [GitHub Issue Tracker](https://github.com/PHLAK/SemVer/issues). 184 | 185 | Copyright 186 | --------- 187 | 188 | This project is liscensed under the [MIT License](https://github.com/PHLAK/SemVer/blob/master/LICENSE). 189 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phlak/semver", 3 | "description": "Semantic versioning helper library", 4 | "type": "library", 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "Chris Kankiewicz", 9 | "email": "Chris@ChrisKankiewicz.com" 10 | } 11 | ], 12 | "funding": [ 13 | { 14 | "type": "github", 15 | "url": "https://github.com/sponsors/PHLAK" 16 | }, 17 | { 18 | "type": "paypal", 19 | "url": "https://paypal.me/ChrisKankiewicz" 20 | } 21 | ], 22 | "support": { 23 | "issues": "https://github.com/PHLAK/SemVer/issues" 24 | }, 25 | "require": { 26 | "php": "^8.1 || ^8.2 || ^8.3 || ^8.4" 27 | }, 28 | "require-dev": { 29 | "phlak/coding-standards": "^4.0", 30 | "phpstan/phpstan": "^2.0", 31 | "yoast/phpunit-polyfills": "^3.0" 32 | }, 33 | "autoload": { 34 | "psr-4": { 35 | "PHLAK\\SemVer\\": "src/" 36 | }, 37 | "files": ["src/Support/helpers.php"] 38 | }, 39 | "autoload-dev": { 40 | "psr-4": { 41 | "PHLAK\\Semver\\Tests\\": "tests/" 42 | } 43 | }, 44 | "config": { 45 | "sort-packages": true, 46 | "optimize-autoloader": true, 47 | "allow-plugins": { 48 | "composer/package-versions-deprecated": true 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /phpstan-ignores.neon: -------------------------------------------------------------------------------- 1 | parameters: 2 | ignoreErrors: 3 | - message: "/^Method .+ throws checked exception .+ but it's missing from the PHPDoc @throws tag.$/" 4 | path: tests/* 5 | -------------------------------------------------------------------------------- /phpstan.neon.dist: -------------------------------------------------------------------------------- 1 | parameters: 2 | 3 | paths: 4 | - src 5 | - tests 6 | 7 | level: max 8 | 9 | checkFunctionNameCase: true 10 | 11 | exceptions: 12 | implicitThrows: false 13 | 14 | check: 15 | missingCheckedExceptionInThrows: true 16 | tooWideThrowType: true 17 | 18 | uncheckedExceptionClasses: 19 | - 'RuntimeException' 20 | - 'PHPUnit\Framework\Exception' 21 | 22 | includes: 23 | - phpstan-ignores.neon 24 | -------------------------------------------------------------------------------- /semver.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PHLAK/SemVer/59dc259f7b734bcdf17c2072c35131e0b0e250d3/semver.png -------------------------------------------------------------------------------- /src/Enums/Compare.php: -------------------------------------------------------------------------------- 1 | [[$version1->major], [$version2->major]], 21 | Compare::MINOR => [[$version1->major, $version1->minor], [$version2->major, $version2->minor]], 22 | default => [[$version1->major, $version1->minor, $version1->patch], [$version2->major, $version2->minor, $version2->patch]] 23 | }; 24 | 25 | $baseComparison = $v1 <=> $v2; 26 | 27 | if ($baseComparison !== 0 || $comparison !== Compare::FULL) { 28 | return $baseComparison; 29 | } 30 | 31 | if ($version1->preRelease !== null && $version2->preRelease === null) { 32 | return -1; 33 | } 34 | 35 | if ($version1->preRelease === null && $version2->preRelease !== null) { 36 | return 1; 37 | } 38 | 39 | $v1preReleaseParts = explode('.', $version1->preRelease ?? ''); 40 | $v2preReleaseParts = explode('.', $version2->preRelease ?? ''); 41 | 42 | $preReleases1 = array_pad($v1preReleaseParts, count($v2preReleaseParts), null); 43 | $preReleases2 = array_pad($v2preReleaseParts, count($v1preReleaseParts), null); 44 | 45 | return $preReleases1 <=> $preReleases2; 46 | } 47 | 48 | /** 49 | * Check if this Version object is greater than another. 50 | * 51 | * @param Version $version An instance of SemVer/Version 52 | * 53 | * @return bool True if this Version object is greater than the comparing 54 | * object, otherwise false 55 | */ 56 | public function gt(Version $version, Compare $comparison = Compare::FULL): bool 57 | { 58 | return self::compare($this, $version, $comparison) > 0; 59 | } 60 | 61 | /** 62 | * Check if this Version object is less than another. 63 | * 64 | * @param Version $version An instance of SemVer/Version 65 | * 66 | * @return bool True if this Version object is less than the comparing 67 | * object, otherwise false 68 | */ 69 | public function lt(Version $version, Compare $comparison = Compare::FULL): bool 70 | { 71 | return self::compare($this, $version, $comparison) < 0; 72 | } 73 | 74 | /** 75 | * Check if this Version object is equal to than another. 76 | * 77 | * @param Version $version An instance of SemVer/Version 78 | * 79 | * @return bool True if this Version object is equal to the comparing 80 | * object, otherwise false 81 | */ 82 | public function eq(Version $version, Compare $comparison = Compare::FULL): bool 83 | { 84 | return self::compare($this, $version, $comparison) === 0; 85 | } 86 | 87 | /** 88 | * Check if this Version object is not equal to another. 89 | * 90 | * @param Version $version An instance of SemVer/Version 91 | * 92 | * @return bool True if this Version object is not equal to the comparing 93 | * object, otherwise false 94 | */ 95 | public function neq(Version $version, Compare $comparison = Compare::FULL): bool 96 | { 97 | return self::compare($this, $version, $comparison) !== 0; 98 | } 99 | 100 | /** 101 | * Check if this Version object is greater than or equal to another. 102 | * 103 | * @param Version $version An instance of SemVer/Version 104 | * 105 | * @return bool True if this Version object is greater than or equal to the 106 | * comparing object, otherwise false 107 | */ 108 | public function gte(Version $version, Compare $comparison = Compare::FULL): bool 109 | { 110 | return self::compare($this, $version, $comparison) >= 0; 111 | } 112 | 113 | /** 114 | * Check if this Version object is less than or equal to another. 115 | * 116 | * @param Version $version An instance of SemVer/Version 117 | * 118 | * @return bool True if this Version object is less than or equal to the 119 | * comparing object, otherwise false 120 | */ 121 | public function lte(Version $version, Compare $comparison = Compare::FULL): bool 122 | { 123 | return self::compare($this, $version, $comparison) <= 0; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/Traits/Incrementable.php: -------------------------------------------------------------------------------- 1 | setMajor($this->major + 1); 15 | 16 | return $this; 17 | } 18 | 19 | /** 20 | * Increment the minor version value by one. 21 | * 22 | * @return static This Version object 23 | */ 24 | public function incrementMinor(): static 25 | { 26 | $this->setMinor($this->minor + 1); 27 | 28 | return $this; 29 | } 30 | 31 | /** 32 | * Increment the patch version value by one. 33 | * 34 | * @return static This Version object 35 | */ 36 | public function incrementPatch(): static 37 | { 38 | $this->setPatch($this->patch + 1); 39 | 40 | return $this; 41 | } 42 | 43 | /** 44 | * Increment the pre-release version value by one. 45 | * 46 | * @return static This Version object 47 | */ 48 | public function incrementPreRelease(): static 49 | { 50 | if (empty($this->preRelease)) { 51 | $this->incrementPatch(); 52 | $this->setPreRelease('1'); 53 | 54 | return $this; 55 | } 56 | 57 | $identifiers = explode('.', $this->preRelease); 58 | 59 | if (! is_numeric(end($identifiers))) { 60 | $this->setPreRelease(implode('.', [$this->preRelease, '1'])); 61 | 62 | return $this; 63 | } 64 | 65 | array_push($identifiers, (string) ((int) array_pop($identifiers) + 1)); 66 | 67 | $this->setPreRelease(implode('.', $identifiers)); 68 | 69 | return $this; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/Version.php: -------------------------------------------------------------------------------- 1 | setVersion($version); 47 | } 48 | 49 | /** 50 | * Magic get method; provides access to version properties. 51 | * 52 | * @param string $property Version property 53 | * 54 | * @return mixed Version property value 55 | */ 56 | public function __get(string $property) 57 | { 58 | return $this->$property; 59 | } 60 | 61 | /** 62 | * Magic toString method; allows object interaction as if it were a string. 63 | * 64 | * @return string Current version string 65 | */ 66 | public function __toString(): string 67 | { 68 | $version = implode('.', [$this->major, $this->minor, $this->patch]); 69 | 70 | if (! empty($this->preRelease)) { 71 | $version .= '-' . $this->preRelease; 72 | } 73 | 74 | if (! empty($this->build)) { 75 | $version .= '+' . $this->build; 76 | } 77 | 78 | return $version; 79 | } 80 | 81 | /** 82 | * Attempt to parse an incomplete version string. 83 | * 84 | * Examples: 'v1', 'v1.2', 'v1-beta.4', 'v1.3+007' 85 | * 86 | * @param string $version Version string 87 | * 88 | * @throws \PHLAK\SemVer\Exceptions\InvalidVersionException 89 | * 90 | * @return static This Version object 91 | */ 92 | public static function parse(string $version): static 93 | { 94 | $semverRegex = '/^v?(?\d+)(?:\.(?\d+)(?:\.(?\d+))?)?(?:-(?[0-9A-Za-z-.]+))?(?:\+(?[0-9A-Za-z-.]+)?)?$/'; 95 | 96 | if (! preg_match($semverRegex, $version, $matches)) { 97 | throw new InvalidVersionException('Invalid semantic version string provided'); 98 | } 99 | 100 | $version = sprintf('%s.%s.%s', $matches['major'], $matches['minor'] ?? 0, $matches['patch'] ?? 0); 101 | 102 | if (! empty($matches['pre_release'])) { 103 | $version .= '-' . $matches['pre_release']; 104 | } 105 | 106 | if (! empty($matches['build'])) { 107 | $version .= '+' . $matches['build']; 108 | } 109 | 110 | return new static($version); 111 | } 112 | 113 | /** Serialize version to JSON. */ 114 | public function jsonSerialize(): mixed 115 | { 116 | return (string) $this; 117 | } 118 | 119 | /** 120 | * Set (override) the entire version value. 121 | * 122 | * @param string $version Version string 123 | * 124 | * @throws \PHLAK\SemVer\Exceptions\InvalidVersionException 125 | * 126 | * @return static This Version object 127 | */ 128 | public function setVersion(string $version): static 129 | { 130 | $semverRegex = '/^v?(?\d+)\.(?\d+)\.(?\d+)(?:-(?[0-9A-Za-z-.]+))?(?:\+(?[0-9A-Za-z-.]+)?)?$/'; 131 | 132 | if (! preg_match($semverRegex, $version, $matches, PREG_UNMATCHED_AS_NULL)) { 133 | throw new InvalidVersionException('Invalid semantic version string provided'); 134 | } 135 | 136 | $this->major = (int) $matches['major']; 137 | $this->minor = (int) $matches['minor']; 138 | $this->patch = (int) $matches['patch']; 139 | $this->preRelease = $matches['pre_release'] ?? null; 140 | $this->build = $matches['build'] ?? null; 141 | 142 | return $this; 143 | } 144 | 145 | /** 146 | * Set the major version to a custom value. 147 | * 148 | * @param int $value Positive integer value 149 | * 150 | * @return static This Version object 151 | */ 152 | public function setMajor(int $value): static 153 | { 154 | $this->major = $value; 155 | $this->setMinor(0); 156 | 157 | return $this; 158 | } 159 | 160 | /** 161 | * Set the minor version to a custom value. 162 | * 163 | * @param int $value Positive integer value 164 | * 165 | * @return static This Version object 166 | */ 167 | public function setMinor(int $value): static 168 | { 169 | $this->minor = $value; 170 | $this->setPatch(0); 171 | 172 | return $this; 173 | } 174 | 175 | /** 176 | * Set the patch version to a custom value. 177 | * 178 | * @param int $value Positive integer value 179 | * 180 | * @return static This Version object 181 | */ 182 | public function setPatch(int $value): static 183 | { 184 | $this->patch = $value; 185 | $this->setPreRelease(null); 186 | $this->setBuild(null); 187 | 188 | return $this; 189 | } 190 | 191 | /** 192 | * Set the pre-release string to a custom value. 193 | * 194 | * @param string|null $value A new pre-release value 195 | * 196 | * @return static This Version object 197 | */ 198 | public function setPreRelease($value): static 199 | { 200 | $this->preRelease = $value; 201 | 202 | return $this; 203 | } 204 | 205 | /** 206 | * Set the build string to a custom value. 207 | * 208 | * @param string|null $value A new build value 209 | * 210 | * @return static This Version object 211 | */ 212 | public function setBuild($value): static 213 | { 214 | $this->build = $value; 215 | 216 | return $this; 217 | } 218 | 219 | /** 220 | * Get the version string prefixed with a custom string. 221 | * 222 | * @param string $prefix String to prepend to the version string 223 | * (default: 'v') 224 | * 225 | * @return string Prefixed version string 226 | */ 227 | public function prefix(string $prefix = 'v'): string 228 | { 229 | return $prefix . (string) $this; 230 | } 231 | 232 | /** 233 | * Determine if the version is a pre-release. 234 | * 235 | * @return bool Returns true if the version is a pre-release, false otherwise 236 | */ 237 | public function isPreRelease(): bool 238 | { 239 | return ! empty($this->preRelease); 240 | } 241 | 242 | /** 243 | * Determine if the version has a build string. 244 | * 245 | * @return bool Returns true if the version has a build string, false otherwise 246 | */ 247 | public function hasBuild(): bool 248 | { 249 | return ! empty($this->build); 250 | } 251 | } 252 | --------------------------------------------------------------------------------