Repository: phar-io/version Branch: master Commit: 5eeb03f1ee82 Files: 45 Total size: 79.6 KB Directory structure: gitextract_esjl8x2z/ ├── .gitattributes ├── .gitignore ├── .php_cs.dist ├── CHANGELOG.md ├── LICENSE ├── README.md ├── build.xml ├── composer.json ├── phive.xml ├── phpunit.xml ├── psalm.xml ├── src/ │ ├── BuildMetaData.php │ ├── PreReleaseSuffix.php │ ├── Version.php │ ├── VersionConstraintParser.php │ ├── VersionConstraintValue.php │ ├── VersionNumber.php │ ├── constraints/ │ │ ├── AbstractVersionConstraint.php │ │ ├── AndVersionConstraintGroup.php │ │ ├── AnyVersionConstraint.php │ │ ├── ExactVersionConstraint.php │ │ ├── GreaterThanOrEqualToVersionConstraint.php │ │ ├── OrVersionConstraintGroup.php │ │ ├── SpecificMajorAndMinorVersionConstraint.php │ │ ├── SpecificMajorVersionConstraint.php │ │ └── VersionConstraint.php │ └── exceptions/ │ ├── Exception.php │ ├── InvalidPreReleaseSuffixException.php │ ├── InvalidVersionException.php │ ├── NoBuildMetaDataException.php │ ├── NoPreReleaseSuffixException.php │ └── UnsupportedVersionConstraintException.php └── tests/ ├── Integration/ │ ├── CompliesTest.php │ └── VersionConstraintParserTest.php └── Unit/ ├── AbstractVersionConstraintTest.php ├── AndVersionConstraintGroupTest.php ├── AnyVersionConstraintTest.php ├── BuildMetaDataTest.php ├── ExactVersionConstraintTest.php ├── GreaterThanOrEqualToVersionConstraintTest.php ├── OrVersionConstraintGroupTest.php ├── PreReleaseSuffixTest.php ├── SpecificMajorAndMinorVersionConstraintTest.php ├── SpecificMajorVersionConstraintTest.php └── VersionTest.php ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ /tests export-ignore /.gitattributes export-ignore /.gitignore export-ignore /.php_cs.dist export-ignore /.travis.yml export-ignore /build.xml export-ignore /phive.xml export-ignore /phpunit.xml export-ignore /psalm.xml export-ignore ================================================ FILE: .gitignore ================================================ /.github/ /.idea /.php_cs.cache /composer.lock /tools /vendor build/coverage .phpunit.result.cache ================================================ FILE: .php_cs.dist ================================================ setRiskyAllowed(true) ->setRules( [ 'align_multiline_comment' => true, 'array_indentation' => true, 'array_syntax' => ['syntax' => 'short'], 'binary_operator_spaces' => [ 'operators' => [ '=' => 'align', '=>' => 'align', ], ], 'blank_line_after_namespace' => true, 'blank_line_after_opening_tag' => false, 'blank_line_before_statement' => [ 'statements' => [ 'break', 'continue', 'declare', 'do', 'for', 'foreach', 'if', 'include', 'include_once', 'require', 'require_once', 'return', 'switch', 'throw', 'try', 'while', 'yield', ], ], 'braces' => [ 'allow_single_line_closure' => false, 'position_after_anonymous_constructs' => 'same', 'position_after_control_structures' => 'same', 'position_after_functions_and_oop_constructs' => 'same' ], 'cast_spaces' => ['space' => 'none'], // This fixer removes the blank line at class start, no way to disable that, so we disable the fixer :( //'class_attributes_separation' => ['elements' => ['const', 'method', 'property']], 'combine_consecutive_issets' => true, 'combine_consecutive_unsets' => true, 'compact_nullable_typehint' => true, 'concat_space' => ['spacing' => 'one'], 'date_time_immutable' => true, 'declare_equal_normalize' => ['space' => 'single'], 'declare_strict_types' => true, 'dir_constant' => true, 'elseif' => true, 'encoding' => true, 'full_opening_tag' => true, 'fully_qualified_strict_types' => true, 'function_declaration' => [ 'closure_function_spacing' => 'one' ], 'header_comment' => false, 'indentation_type' => true, 'is_null' => true, 'line_ending' => true, 'list_syntax' => ['syntax' => 'short'], 'logical_operators' => true, 'lowercase_cast' => true, 'lowercase_constants' => true, 'lowercase_keywords' => true, 'lowercase_static_reference' => true, 'magic_constant_casing' => true, 'method_argument_space' => ['ensure_fully_multiline' => true], 'modernize_types_casting' => true, 'multiline_comment_opening_closing' => true, 'multiline_whitespace_before_semicolons' => true, 'native_constant_invocation' => true, 'native_function_casing' => true, 'native_function_invocation' => true, 'new_with_braces' => false, 'no_alias_functions' => true, 'no_alternative_syntax' => true, 'no_blank_lines_after_class_opening' => false, 'no_blank_lines_after_phpdoc' => true, 'no_blank_lines_before_namespace' => true, 'no_closing_tag' => true, 'no_empty_comment' => true, 'no_empty_phpdoc' => true, 'no_empty_statement' => true, 'no_extra_blank_lines' => true, 'no_homoglyph_names' => true, 'no_leading_import_slash' => true, 'no_leading_namespace_whitespace' => true, 'no_mixed_echo_print' => ['use' => 'print'], 'no_multiline_whitespace_around_double_arrow' => true, 'no_null_property_initialization' => true, 'no_php4_constructor' => true, 'no_short_bool_cast' => true, 'no_short_echo_tag' => true, 'no_singleline_whitespace_before_semicolons' => true, 'no_spaces_after_function_name' => true, 'no_spaces_inside_parenthesis' => true, 'no_superfluous_elseif' => true, 'no_superfluous_phpdoc_tags' => true, 'no_trailing_comma_in_list_call' => true, 'no_trailing_comma_in_singleline_array' => true, 'no_trailing_whitespace' => true, 'no_trailing_whitespace_in_comment' => true, 'no_unneeded_control_parentheses' => false, 'no_unneeded_curly_braces' => false, 'no_unneeded_final_method' => true, 'no_unreachable_default_argument_value' => true, 'no_unset_on_property' => true, 'no_unused_imports' => true, 'no_useless_else' => true, 'no_useless_return' => true, 'no_whitespace_before_comma_in_array' => true, 'no_whitespace_in_blank_line' => true, 'non_printable_character' => true, 'normalize_index_brace' => true, 'object_operator_without_whitespace' => true, 'ordered_class_elements' => [ 'order' => [ 'use_trait', 'constant_public', 'constant_protected', 'constant_private', 'property_public_static', 'property_protected_static', 'property_private_static', 'property_public', 'property_protected', 'property_private', 'method_public_static', 'construct', 'destruct', 'magic', 'phpunit', 'method_public', 'method_protected', 'method_private', 'method_protected_static', 'method_private_static', ], ], 'ordered_imports' => true, 'phpdoc_add_missing_param_annotation' => true, 'phpdoc_align' => true, 'phpdoc_annotation_without_dot' => true, 'phpdoc_indent' => true, 'phpdoc_no_access' => true, 'phpdoc_no_empty_return' => true, 'phpdoc_no_package' => true, 'phpdoc_order' => true, 'phpdoc_return_self_reference' => true, 'phpdoc_scalar' => true, 'phpdoc_separation' => true, 'phpdoc_single_line_var_spacing' => true, 'phpdoc_to_comment' => true, 'phpdoc_trim' => true, 'phpdoc_trim_consecutive_blank_line_separation' => true, 'phpdoc_types' => ['groups' => ['simple', 'meta']], 'phpdoc_types_order' => true, 'phpdoc_to_return_type' => true, 'phpdoc_var_without_name' => true, 'pow_to_exponentiation' => true, 'protected_to_private' => true, 'return_assignment' => true, 'return_type_declaration' => ['space_before' => 'none'], 'self_accessor' => false, 'semicolon_after_instruction' => true, 'set_type_to_cast' => true, 'short_scalar_cast' => true, 'simplified_null_return' => true, 'single_blank_line_at_eof' => true, 'single_import_per_statement' => true, 'single_line_after_imports' => true, 'single_quote' => true, 'standardize_not_equals' => true, 'ternary_to_null_coalescing' => true, 'trailing_comma_in_multiline_array' => false, 'trim_array_spaces' => true, 'unary_operator_spaces' => true, 'visibility_required' => [ 'elements' => [ 'const', 'method', 'property', ], ], 'void_return' => true, 'whitespace_after_comma_in_array' => true, 'yoda_style' => false ] ) ->setFinder( PhpCsFixer\Finder::create() ->files() ->in(__DIR__ . '/src') ->in(__DIR__ . '/tests') ->notName('*.phpt') ); ================================================ FILE: CHANGELOG.md ================================================ # Changelog All notable changes to phar-io/version are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. ## [3.3.0] - 2024-??-?? ### Fixed - [#35](https://github.com/phar-io/version/issues/35): major version only not supported, e.g. ^6 ## [3.2.1] - 2022-02-21 ### Fixed - Have ExactVersionConstraint honor build metadata (added in 3.2.0) ## [3.2.0] - 2022-02-21 ### Added - Build metadata is now supported and considered for equality checks only ## [3.1.1] - 2022-02-07 ### Fixed - [#28](https://github.com/phar-io/version/issues/28): `VersionConstraintParser` does not support logical OR represented by single pipe (|) (Thanks @llaville) ## [3.1.0] - 2021-02-23 ### Changed - Internal Refactoring - More scalar types ### Added - [#24](https://github.com/phar-io/version/issues/24): `Version::getOriginalString()` added (Thanks @addshore) - Version constraints using the caret operator (`^`) now honor pre-1.0 releases, e.g. `^0.3` translates to `0.3.*`) - Various integration tests for version constraint processing ### Fixed - [#23](https://github.com/phar-io/version/pull/23): Tilde operator without patch level ## [3.0.4] - 14.12.2020 ### Fixed - [#22](https://github.com/phar-io/version/pull/22): make dev suffix rank works for uppercase too ## [3.0.3] - 30.11.2020 ### Added - Comparator method `Version::equals()` added ## [3.0.2] - 27.06.2020 This release now supports PHP 7.2+ and PHP ^8.0. No other changes included. ## [3.0.1] - 09.05.2020 __Potential BC Break Notice:__ `Version::getVersionString()` no longer returns `v` prefixes in case the "input" string contained one. These are not part of the semver specs (see https://semver.org/#is-v123-a-semantic-version) and get stripped out. As of Version 3.1.0 `Version::getOriginalString()` can be used to still retrieve it as given. ### Changed - Internal Refactoring - More scalar types ### Fixed - Fixed Constraint processing Regression for ^1.2 and ~1.2 ## [3.0.0] - 05.05.2020 ### Changed - Require PHP 7.2+ - All code now uses strict mode - Scalar types have been added as needed ### Added - The technically invalid format using 'v' prefix ("v1.2.3") is now properly supported ## [2.0.1] - 08.07.2018 ### Fixed - Versions without a pre-release suffix are now always considered greater than versions with a pre-release suffix. Example: `3.0.0 > 3.0.0-alpha.1` ## [2.0.0] - 23.06.2018 Changes to public API: - `PreReleaseSuffix::construct()`: optional parameter `$number` removed - `PreReleaseSuffix::isGreaterThan()`: introduced - `Version::hasPreReleaseSuffix()`: introduced ### Added - [#11](https://github.com/phar-io/version/issues/11): Added support for pre-release version suffixes. Supported values are: - `dev` - `beta` (also abbreviated form `b`) - `rc` - `alpha` (also abbreviated form `a`) - `patch` (also abbreviated form `p`) All values can be followed by a number, e.g. `beta3`. When comparing versions, the pre-release suffix is taken into account. Example: `1.5.0 > 1.5.0-beta1 > 1.5.0-alpha3 > 1.5.0-alpha2 > 1.5.0-dev11` ### Changed - reorganized the source directories ### Fixed - [#10](https://github.com/phar-io/version/issues/10): Version numbers containing a numeric suffix as seen in Debian packages are now supported. [3.3.0]: https://github.com/phar-io/version/compare/3.2.1...3.3.0 [3.2.1]: https://github.com/phar-io/version/compare/3.2.1...3.2.1 [3.2.0]: https://github.com/phar-io/version/compare/3.1.1...3.2.0 [3.1.1]: https://github.com/phar-io/version/compare/3.1.0...3.1.1 [3.1.0]: https://github.com/phar-io/version/compare/3.0.4...3.1.0 [3.0.4]: https://github.com/phar-io/version/compare/3.0.3...3.0.4 [3.0.3]: https://github.com/phar-io/version/compare/3.0.2...3.0.3 [3.0.2]: https://github.com/phar-io/version/compare/3.0.1...3.0.2 [3.0.1]: https://github.com/phar-io/version/compare/3.0.0...3.0.1 [3.0.0]: https://github.com/phar-io/version/compare/2.0.1...3.0.0 [2.0.1]: https://github.com/phar-io/version/compare/2.0.0...2.0.1 [2.0.0]: https://github.com/phar-io/version/compare/1.0.1...2.0.0 ================================================ FILE: LICENSE ================================================ Copyright (c) 2016-2017 Arne Blankerts , Sebastian Heuer and contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the copyright holder nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: README.md ================================================ # Version Library for handling version information and constraints [![CI](https://github.com/phar-io/version/actions/workflows/ci.yml/badge.svg)](https://github.com/phar-io/version/actions/workflows/ci.yml) ## Installation You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): composer require phar-io/version If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: composer require --dev phar-io/version ## Version constraints A Version constraint describes a range of versions or a discrete version number. The format of version numbers follows the schema of [semantic versioning](http://semver.org): `..`. A constraint might contain an operator that describes the range. Beside the typical mathematical operators like `<=`, `>=`, there are two special operators: *Caret operator*: `^1.0` can be written as `>=1.0.0 <2.0.0` and read as »every Version within major version `1`«. *Tilde operator*: `~1.0.0` can be written as `>=1.0.0 <1.1.0` and read as »every version within minor version `1.1`. The behavior of tilde operator depends on whether a patch level version is provided or not. If no patch level is provided, tilde operator behaves like the caret operator: `~1.0` is identical to `^1.0`. ## Usage examples Parsing version constraints and check discrete versions for compliance: ```php use PharIo\Version\Version; use PharIo\Version\VersionConstraintParser; $parser = new VersionConstraintParser(); $caret_constraint = $parser->parse( '^7.0' ); $caret_constraint->complies( new Version( '7.0.17' ) ); // true $caret_constraint->complies( new Version( '7.1.0' ) ); // true $caret_constraint->complies( new Version( '6.4.34' ) ); // false $tilde_constraint = $parser->parse( '~1.1.0' ); $tilde_constraint->complies( new Version( '1.1.4' ) ); // true $tilde_constraint->complies( new Version( '1.2.0' ) ); // false ``` As of version 2.0.0, pre-release labels are supported and taken into account when comparing versions: ```php $leftVersion = new PharIo\Version\Version('3.0.0-alpha.1'); $rightVersion = new PharIo\Version\Version('3.0.0-alpha.2'); $leftVersion->isGreaterThan($rightVersion); // false $rightVersion->isGreaterThan($leftVersion); // true ``` ================================================ FILE: build.xml ================================================ ================================================ FILE: composer.json ================================================ { "name": "phar-io/version", "description": "Library for handling version information and constraints", "license": "BSD-3-Clause", "authors": [ { "name": "Arne Blankerts", "email": "arne@blankerts.de", "role": "Developer" }, { "name": "Sebastian Heuer", "email": "sebastian@phpeople.de", "role": "Developer" }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "Developer" } ], "support": { "issues": "https://github.com/phar-io/version/issues" }, "require": { "php": "^7.2 || ^8.0" }, "autoload": { "classmap": [ "src/" ] } } ================================================ FILE: phive.xml ================================================ ================================================ FILE: phpunit.xml ================================================ tests src ================================================ FILE: psalm.xml ================================================ ================================================ FILE: src/BuildMetaData.php ================================================ , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; class BuildMetaData { /** @var string */ private $value; public function __construct(string $value) { $this->value = $value; } public function asString(): string { return $this->value; } public function equals(BuildMetaData $other): bool { return $this->asString() === $other->asString(); } } ================================================ FILE: src/PreReleaseSuffix.php ================================================ 0, 'a' => 1, 'alpha' => 1, 'b' => 2, 'beta' => 2, 'rc' => 3, 'p' => 4, 'pl' => 4, 'patch' => 4, ]; /** @var string */ private $value; /** @var int */ private $valueScore; /** @var int */ private $number = 0; /** @var string */ private $full; /** * @throws InvalidPreReleaseSuffixException */ public function __construct(string $value) { $this->parseValue($value); } public function asString(): string { return $this->full; } public function getValue(): string { return $this->value; } public function getNumber(): ?int { return $this->number; } public function isGreaterThan(PreReleaseSuffix $suffix): bool { if ($this->valueScore > $suffix->valueScore) { return true; } if ($this->valueScore < $suffix->valueScore) { return false; } return $this->getNumber() > $suffix->getNumber(); } private function mapValueToScore(string $value): int { $value = \strtolower($value); return self::valueScoreMap[$value]; } private function parseValue(string $value): void { $regex = '/-?((dev|beta|b|rc|alpha|a|patch|p|pl)\.?(\d*)).*$/i'; if (\preg_match($regex, $value, $matches) !== 1) { throw new InvalidPreReleaseSuffixException(\sprintf('Invalid label %s', $value)); } $this->full = $matches[1]; $this->value = $matches[2]; if ($matches[3] !== '') { $this->number = (int)$matches[3]; } $this->valueScore = $this->mapValueToScore($matches[2]); } } ================================================ FILE: src/Version.php ================================================ , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; class Version { /** @var string */ private $originalVersionString; /** @var VersionNumber */ private $major; /** @var VersionNumber */ private $minor; /** @var VersionNumber */ private $patch; /** @var null|PreReleaseSuffix */ private $preReleaseSuffix; /** @var null|BuildMetaData */ private $buildMetadata; public function __construct(string $versionString) { $this->ensureVersionStringIsValid($versionString); $this->originalVersionString = $versionString; } /** * @throws NoPreReleaseSuffixException */ public function getPreReleaseSuffix(): PreReleaseSuffix { if ($this->preReleaseSuffix === null) { throw new NoPreReleaseSuffixException('No pre-release suffix set'); } return $this->preReleaseSuffix; } public function getOriginalString(): string { return $this->originalVersionString; } public function getVersionString(): string { $str = \sprintf( '%d.%d.%d', $this->getMajor()->getValue() ?? 0, $this->getMinor()->getValue() ?? 0, $this->getPatch()->getValue() ?? 0 ); if (!$this->hasPreReleaseSuffix()) { return $str; } return $str . '-' . $this->getPreReleaseSuffix()->asString(); } public function hasPreReleaseSuffix(): bool { return $this->preReleaseSuffix !== null; } public function equals(Version $other): bool { if ($this->getVersionString() !== $other->getVersionString()) { return false; } if ($this->hasBuildMetaData() !== $other->hasBuildMetaData()) { return false; } if ($this->hasBuildMetaData() && $other->hasBuildMetaData() && !$this->getBuildMetaData()->equals($other->getBuildMetaData())) { return false; } return true; } public function isGreaterThan(Version $version): bool { if ($version->getMajor()->getValue() > $this->getMajor()->getValue()) { return false; } if ($version->getMajor()->getValue() < $this->getMajor()->getValue()) { return true; } if ($version->getMinor()->getValue() > $this->getMinor()->getValue()) { return false; } if ($version->getMinor()->getValue() < $this->getMinor()->getValue()) { return true; } if ($version->getPatch()->getValue() > $this->getPatch()->getValue()) { return false; } if ($version->getPatch()->getValue() < $this->getPatch()->getValue()) { return true; } if (!$version->hasPreReleaseSuffix() && !$this->hasPreReleaseSuffix()) { return false; } if ($version->hasPreReleaseSuffix() && !$this->hasPreReleaseSuffix()) { return true; } if (!$version->hasPreReleaseSuffix() && $this->hasPreReleaseSuffix()) { return false; } return $this->getPreReleaseSuffix()->isGreaterThan($version->getPreReleaseSuffix()); } public function getMajor(): VersionNumber { return $this->major; } public function getMinor(): VersionNumber { return $this->minor; } public function getPatch(): VersionNumber { return $this->patch; } /** * @psalm-assert-if-true BuildMetaData $this->buildMetadata * @psalm-assert-if-true BuildMetaData $this->getBuildMetaData() */ public function hasBuildMetaData(): bool { return $this->buildMetadata !== null; } /** * @throws NoBuildMetaDataException */ public function getBuildMetaData(): BuildMetaData { if (!$this->hasBuildMetaData()) { throw new NoBuildMetaDataException('No build metadata set'); } return $this->buildMetadata; } /** * @param string[] $matches * * @throws InvalidPreReleaseSuffixException */ private function parseVersion(array $matches): void { $this->major = new VersionNumber((int)$matches['Major']); $this->minor = isset($matches['Minor']) ? new VersionNumber((int)$matches['Minor']) : new VersionNumber(0); $this->patch = isset($matches['Patch']) ? new VersionNumber((int)$matches['Patch']) : new VersionNumber(0); if (isset($matches['PreReleaseSuffix']) && $matches['PreReleaseSuffix'] !== '') { $this->preReleaseSuffix = new PreReleaseSuffix($matches['PreReleaseSuffix']); } if (isset($matches['BuildMetadata'])) { $this->buildMetadata = new BuildMetaData($matches['BuildMetadata']); } } /** * @param string $version * * @throws InvalidVersionException */ private function ensureVersionStringIsValid($version): void { $regex = '/^v? (?P0|[1-9]\d*) (\\. (?P0|[1-9]\d*) )? (\\. (?P0|[1-9]\d*) )? (?: - (?(?:(dev|beta|b|rc|alpha|a|patch|p|pl)\.?\d*)) )? (?: \\+ (?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-@]+)*) )? $/xi'; if (\preg_match($regex, $version, $matches) !== 1) { throw new InvalidVersionException( \sprintf("Version string '%s' does not follow SemVer semantics", $version) ); } $this->parseVersion($matches); } } ================================================ FILE: src/VersionConstraintParser.php ================================================ , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; class VersionConstraintParser { /** * @throws UnsupportedVersionConstraintException */ public function parse(string $value): VersionConstraint { if (\strpos($value, '|') !== false) { return $this->handleOrGroup($value); } if (!\preg_match('/^[\^~*]?v?[\d.*]+(?:-.*)?$/i', $value)) { throw new UnsupportedVersionConstraintException( \sprintf('Version constraint %s is not supported.', $value) ); } switch ($value[0]) { case '~': return $this->handleTildeOperator($value); case '^': return $this->handleCaretOperator($value); } $constraint = new VersionConstraintValue($value); if ($constraint->getMajor()->isAny()) { return new AnyVersionConstraint(); } if ($constraint->getMinor()->isAny()) { return new SpecificMajorVersionConstraint( $constraint->getVersionString(), $constraint->getMajor()->getValue() ?? 0 ); } if ($constraint->getPatch()->isAny()) { return new SpecificMajorAndMinorVersionConstraint( $constraint->getVersionString(), $constraint->getMajor()->getValue() ?? 0, $constraint->getMinor()->getValue() ?? 0 ); } return new ExactVersionConstraint($constraint->getVersionString()); } private function handleOrGroup(string $value): OrVersionConstraintGroup { $constraints = []; foreach (\preg_split('{\s*\|\|?\s*}', \trim($value)) as $groupSegment) { $constraints[] = $this->parse(\trim($groupSegment)); } return new OrVersionConstraintGroup($value, $constraints); } private function handleTildeOperator(string $value): AndVersionConstraintGroup { $constraintValue = new VersionConstraintValue(\substr($value, 1)); if ($constraintValue->getPatch()->isAny()) { return $this->handleCaretOperator($value); } $constraints = [ new GreaterThanOrEqualToVersionConstraint( $value, new Version(\substr($value, 1)) ), new SpecificMajorAndMinorVersionConstraint( $value, $constraintValue->getMajor()->getValue() ?? 0, $constraintValue->getMinor()->getValue() ?? 0 ) ]; return new AndVersionConstraintGroup($value, $constraints); } private function handleCaretOperator(string $value): AndVersionConstraintGroup { $constraintValue = new VersionConstraintValue(\substr($value, 1)); $constraints = [ new GreaterThanOrEqualToVersionConstraint($value, new Version(\substr($value, 1))) ]; if ($constraintValue->getMajor()->getValue() === 0) { $constraints[] = new SpecificMajorAndMinorVersionConstraint( $value, $constraintValue->getMajor()->getValue() ?? 0, $constraintValue->getMinor()->getValue() ?? 0 ); } else { $constraints[] = new SpecificMajorVersionConstraint( $value, $constraintValue->getMajor()->getValue() ?? 0 ); } return new AndVersionConstraintGroup( $value, $constraints ); } } ================================================ FILE: src/VersionConstraintValue.php ================================================ versionString = $versionString; $this->parseVersion($versionString); } public function getLabel(): string { return $this->label; } public function getBuildMetaData(): string { return $this->buildMetaData; } public function getVersionString(): string { return $this->versionString; } public function getMajor(): VersionNumber { return $this->major; } public function getMinor(): VersionNumber { return $this->minor; } public function getPatch(): VersionNumber { return $this->patch; } private function parseVersion(string $versionString): void { $this->extractBuildMetaData($versionString); $this->extractLabel($versionString); $this->stripPotentialVPrefix($versionString); $versionSegments = \explode('.', $versionString); $this->major = new VersionNumber(\is_numeric($versionSegments[0]) ? (int)$versionSegments[0] : null); $minorValue = isset($versionSegments[1]) && \is_numeric($versionSegments[1]) ? (int)$versionSegments[1] : null; $patchValue = isset($versionSegments[2]) && \is_numeric($versionSegments[2]) ? (int)$versionSegments[2] : null; $this->minor = new VersionNumber($minorValue); $this->patch = new VersionNumber($patchValue); } private function extractBuildMetaData(string &$versionString): void { if (\preg_match('/\+(.*)/', $versionString, $matches) === 1) { $this->buildMetaData = $matches[1]; $versionString = \str_replace($matches[0], '', $versionString); } } private function extractLabel(string &$versionString): void { if (\preg_match('/-(.*)/', $versionString, $matches) === 1) { $this->label = $matches[1]; $versionString = \str_replace($matches[0], '', $versionString); } } private function stripPotentialVPrefix(string &$versionString): void { if ($versionString[0] !== 'v') { return; } $versionString = \substr($versionString, 1); } } ================================================ FILE: src/VersionNumber.php ================================================ , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; class VersionNumber { /** @var ?int */ private $value; public function __construct(?int $value) { $this->value = $value; } public function isAny(): bool { return $this->value === null; } public function getValue(): ?int { return $this->value; } } ================================================ FILE: src/constraints/AbstractVersionConstraint.php ================================================ , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; abstract class AbstractVersionConstraint implements VersionConstraint { /** @var string */ private $originalValue; public function __construct(string $originalValue) { $this->originalValue = $originalValue; } public function asString(): string { return $this->originalValue; } } ================================================ FILE: src/constraints/AndVersionConstraintGroup.php ================================================ , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; class AndVersionConstraintGroup extends AbstractVersionConstraint { /** @var VersionConstraint[] */ private $constraints = []; /** * @param VersionConstraint[] $constraints */ public function __construct(string $originalValue, array $constraints) { parent::__construct($originalValue); $this->constraints = $constraints; } public function complies(Version $version): bool { foreach ($this->constraints as $constraint) { if (!$constraint->complies($version)) { return false; } } return true; } } ================================================ FILE: src/constraints/AnyVersionConstraint.php ================================================ , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; class AnyVersionConstraint implements VersionConstraint { public function complies(Version $version): bool { return true; } public function asString(): string { return '*'; } } ================================================ FILE: src/constraints/ExactVersionConstraint.php ================================================ , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; class ExactVersionConstraint extends AbstractVersionConstraint { public function complies(Version $version): bool { $other = $version->getVersionString(); if ($version->hasBuildMetaData()) { $other .= '+' . $version->getBuildMetaData()->asString(); } return $this->asString() === $other; } } ================================================ FILE: src/constraints/GreaterThanOrEqualToVersionConstraint.php ================================================ , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; class GreaterThanOrEqualToVersionConstraint extends AbstractVersionConstraint { /** @var Version */ private $minimalVersion; public function __construct(string $originalValue, Version $minimalVersion) { parent::__construct($originalValue); $this->minimalVersion = $minimalVersion; } public function complies(Version $version): bool { return $version->getVersionString() === $this->minimalVersion->getVersionString() || $version->isGreaterThan($this->minimalVersion); } } ================================================ FILE: src/constraints/OrVersionConstraintGroup.php ================================================ , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; class OrVersionConstraintGroup extends AbstractVersionConstraint { /** @var VersionConstraint[] */ private $constraints = []; /** * @param string $originalValue * @param VersionConstraint[] $constraints */ public function __construct($originalValue, array $constraints) { parent::__construct($originalValue); $this->constraints = $constraints; } public function complies(Version $version): bool { foreach ($this->constraints as $constraint) { if ($constraint->complies($version)) { return true; } } return false; } } ================================================ FILE: src/constraints/SpecificMajorAndMinorVersionConstraint.php ================================================ , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; class SpecificMajorAndMinorVersionConstraint extends AbstractVersionConstraint { /** @var int */ private $major; /** @var int */ private $minor; public function __construct(string $originalValue, int $major, int $minor) { parent::__construct($originalValue); $this->major = $major; $this->minor = $minor; } public function complies(Version $version): bool { if ($version->getMajor()->getValue() !== $this->major) { return false; } return $version->getMinor()->getValue() === $this->minor; } } ================================================ FILE: src/constraints/SpecificMajorVersionConstraint.php ================================================ , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; class SpecificMajorVersionConstraint extends AbstractVersionConstraint { /** @var int */ private $major; public function __construct(string $originalValue, int $major) { parent::__construct($originalValue); $this->major = $major; } public function complies(Version $version): bool { return $version->getMajor()->getValue() === $this->major; } } ================================================ FILE: src/constraints/VersionConstraint.php ================================================ , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; interface VersionConstraint { public function complies(Version $version): bool; public function asString(): string; } ================================================ FILE: src/exceptions/Exception.php ================================================ , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; use Throwable; interface Exception extends Throwable { } ================================================ FILE: src/exceptions/InvalidPreReleaseSuffixException.php ================================================ , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; final class UnsupportedVersionConstraintException extends \RuntimeException implements Exception { } ================================================ FILE: tests/Integration/CompliesTest.php ================================================ , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; use PHPUnit\Framework\TestCase; class CompliesTest extends TestCase { /** * @dataProvider complyingProvider */ public function testCompliesWhenExcepted(string $constraint, string $version): void { $this->assertTrue( (new VersionConstraintParser())->parse($constraint)->complies(new Version($version)) ); } /** * @dataProvider notComplyingProvider */ public function testNotCompliesWhenExcepted(string $constraint, string $version): void { $this->assertFalse( (new VersionConstraintParser())->parse($constraint)->complies(new Version($version)) ); } public function complyingProvider(): array { return [ '1.0.0' => ['1.0.0', '1.0.0'], '~7.0.0' => ['~7.0.0', '7.0.1'], '~7.0' => ['~7.0', '7.0.1'], '~8.0' => ['~8.0', '8.2.3'], '^7.0.0' => ['^7.0.0', '7.0.1'], '^7.0' => ['^7.0', '7.0.1'], '^8.0' => ['^8.0', '8.2.3'], '^7.2 || ^8.0' => ['^7.2 || ^8.0', '7.4.12'], '^7.3 || ^8.0' => ['^7.3 || ^8.0', '8.0.3'], '^7.4 || ^8.0' => ['^7.3 || ^8.0', '8.1.3'], '5.1.*' => ['5.1.*', '5.1.3'], '^0.3' => ['^0.3', '0.3.1'] ]; } public function notComplyingProvider(): array { return [ '1.0.0' => ['1.0.0', '1.0.1'], '~4.6' => ['~4.6', '4.5.3'], '~8.0.0' => ['~8.0.0', '8.1.0'], '5.1.*' => ['5.1.*', '5.2.1'], '5.2.*' => ['5.2.*', '5.1.9'], '^0.3' => ['^0.3', '0.4.1'] ]; } } ================================================ FILE: tests/Integration/VersionConstraintParserTest.php ================================================ , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; use PHPUnit\Framework\TestCase; /** * @covers \PharIo\Version\VersionConstraintParser */ class VersionConstraintParserTest extends TestCase { /** * @dataProvider versionStringProvider * * @param string $versionString */ public function testReturnsExpectedConstraint($versionString, VersionConstraint $expectedConstraint): void { $parser = new VersionConstraintParser; $this->assertEquals($expectedConstraint, $parser->parse($versionString)); } /** * @dataProvider unsupportedVersionStringProvider * * @param string $versionString */ public function testThrowsExceptionIfVersionStringIsNotSupported($versionString): void { $parser = new VersionConstraintParser; $this->expectException(UnsupportedVersionConstraintException::class); $parser->parse($versionString); } public function versionStringProvider(): array { return [ ['1.0.2', new ExactVersionConstraint('1.0.2')], [ '~4.6', new AndVersionConstraintGroup( '~4.6', [ new GreaterThanOrEqualToVersionConstraint('~4.6', new Version('4.6')), new SpecificMajorVersionConstraint('~4.6', 4) ] ) ], [ '~4.6.2', new AndVersionConstraintGroup( '~4.6.2', [ new GreaterThanOrEqualToVersionConstraint('~4.6.2', new Version('4.6.2')), new SpecificMajorAndMinorVersionConstraint('~4.6.2', 4, 6) ] ) ], [ '^2.6.1', new AndVersionConstraintGroup( '^2.6.1', [ new GreaterThanOrEqualToVersionConstraint('^2.6.1', new Version('2.6.1')), new SpecificMajorVersionConstraint('^2.6.1', 2) ] ) ], ['5.1.*', new SpecificMajorAndMinorVersionConstraint('5.1.*', 5, 1)], ['5.*', new SpecificMajorVersionConstraint('5.*', 5)], ['*', new AnyVersionConstraint()], [ '1.0.2 || 1.0.5', new OrVersionConstraintGroup( '1.0.2 || 1.0.5', [ new ExactVersionConstraint('1.0.2'), new ExactVersionConstraint('1.0.5') ] ) ], [ '^5.6 || ^7.0', new OrVersionConstraintGroup( '^5.6 || ^7.0', [ new AndVersionConstraintGroup( '^5.6', [ new GreaterThanOrEqualToVersionConstraint('^5.6', new Version('5.6')), new SpecificMajorVersionConstraint('^5.6', 5) ] ), new AndVersionConstraintGroup( '^7.0', [ new GreaterThanOrEqualToVersionConstraint('^7.0', new Version('7.0')), new SpecificMajorVersionConstraint('^7.0', 7) ] ) ] ) ], [ '^5.3.2 | ^7.0 || ^8.0', new OrVersionConstraintGroup( '^5.3.2 | ^7.0 || ^8.0', [ new AndVersionConstraintGroup( '^5.3.2', [ new GreaterThanOrEqualToVersionConstraint('^5.3.2', new Version('5.3.2')), new SpecificMajorVersionConstraint('^5.3.2', 5) ] ), new AndVersionConstraintGroup( '^7.0', [ new GreaterThanOrEqualToVersionConstraint('^7.0', new Version('7.0')), new SpecificMajorVersionConstraint('^7.0', 7) ] ), new AndVersionConstraintGroup( '^8.0', [ new GreaterThanOrEqualToVersionConstraint('^8.0', new Version('8.0')), new SpecificMajorVersionConstraint('^8.0', 8) ] ) ] ) ], ['7.0.28-1', new ExactVersionConstraint('7.0.28-1')], [ '^3.0.0-alpha1', new AndVersionConstraintGroup( '^3.0.0-alpha1', [ new GreaterThanOrEqualToVersionConstraint('^3.0.0-alpha1', new Version('3.0.0-alpha1')), new SpecificMajorVersionConstraint('^3.0.0-alpha1', 3) ] ) ], [ '^3.0.0-alpha.1', new AndVersionConstraintGroup( '^3.0.0-alpha.1', [ new GreaterThanOrEqualToVersionConstraint('^3.0.0-alpha.1', new Version('3.0.0-alpha.1')), new SpecificMajorVersionConstraint('^3.0.0-alpha.1', 3) ] ) ], [ '^1.0', new AndVersionConstraintGroup( '^1.0', [ new GreaterThanOrEqualToVersionConstraint('^1.0', new Version('1.0')), new SpecificMajorVersionConstraint('^1.0', 1) ] ) ], [ '^1', new AndVersionConstraintGroup( '^1', [ new GreaterThanOrEqualToVersionConstraint('^1', new Version('1')), new SpecificMajorVersionConstraint('^1', 1) ] ) ] ]; } public function unsupportedVersionStringProvider() { return [ ['foo'], ['+1.0.2'], ['>=2.0'], ['^5.6 || >= 7.0'], ['2.0 || foo'] ]; } } ================================================ FILE: tests/Unit/AbstractVersionConstraintTest.php ================================================ , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; use PHPUnit\Framework\TestCase; /** * @covers \PharIo\Version\AbstractVersionConstraint */ class AbstractVersionConstraintTest extends TestCase { public function testAsString(): void { /** @var AbstractVersionConstraint|\PHPUnit_Framework_MockObject_MockObject $constraint */ $constraint = $this->getMockForAbstractClass(AbstractVersionConstraint::class, ['foo']); $this->assertSame('foo', $constraint->asString()); } } ================================================ FILE: tests/Unit/AndVersionConstraintGroupTest.php ================================================ , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; use PHPUnit\Framework\TestCase; /** * @covers \PharIo\Version\AndVersionConstraintGroup */ class AndVersionConstraintGroupTest extends TestCase { public function testReturnsFalseIfOneConstraintReturnsFalse(): void { $firstConstraint = $this->createMock(VersionConstraint::class); $secondConstraint = $this->createMock(VersionConstraint::class); $firstConstraint->expects($this->once()) ->method('complies') ->will($this->returnValue(true)); $secondConstraint->expects($this->once()) ->method('complies') ->will($this->returnValue(false)); $group = new AndVersionConstraintGroup('foo', [$firstConstraint, $secondConstraint]); $this->assertFalse($group->complies(new Version('1.0.0'))); } public function testReturnsTrueIfAllConstraintsReturnsTrue(): void { $firstConstraint = $this->createMock(VersionConstraint::class); $secondConstraint = $this->createMock(VersionConstraint::class); $firstConstraint->expects($this->once()) ->method('complies') ->will($this->returnValue(true)); $secondConstraint->expects($this->once()) ->method('complies') ->will($this->returnValue(true)); $group = new AndVersionConstraintGroup('foo', [$firstConstraint, $secondConstraint]); $this->assertTrue($group->complies(new Version('1.0.0'))); } } ================================================ FILE: tests/Unit/AnyVersionConstraintTest.php ================================================ , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; use PHPUnit\Framework\TestCase; /** * @covers \PharIo\Version\AnyVersionConstraint */ class AnyVersionConstraintTest extends TestCase { public function versionProvider() { return [ [new Version('1.0.2')], [new Version('4.8')], [new Version('0.1.1-dev')] ]; } /** * @dataProvider versionProvider */ public function testReturnsTrue(Version $version): void { $constraint = new AnyVersionConstraint; $this->assertTrue($constraint->complies($version)); } public function testAsString(): void { $this->assertSame('*', (new AnyVersionConstraint())->asString()); } } ================================================ FILE: tests/Unit/BuildMetaDataTest.php ================================================ , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; use PHPUnit\Framework\TestCase; /** * @covers \PharIo\Version\BuildMetaData */ class BuildMetaDataTest extends TestCase { public function testCanBeCreated(): void { $this->assertInstanceOf(BuildMetaData::class, new BuildMetaData('some')); } public function testSetValueCanBeRetrieved(): void { $this->assertSame('some', (new BuildMetaData('some'))->asString()); } public function testTwoIdenticalMetadataStringsAreConsideredEqual(): void { $a = new BuildMetaData('foo'); $b = new BuildMetaData('foo'); $this->assertTrue($a->equals($b)); } public function testTwoNonIdenticalMetadataStringsAreNotConsideredEqual(): void { $a = new BuildMetaData('abc'); $b = new BuildMetaData('def'); $this->assertFalse($a->equals($b)); } } ================================================ FILE: tests/Unit/ExactVersionConstraintTest.php ================================================ , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; use PHPUnit\Framework\TestCase; /** * @covers \PharIo\Version\ExactVersionConstraint */ class ExactVersionConstraintTest extends TestCase { public function compliantVersionProvider() { return [ ['1.0.2', new Version('1.0.2')], ['4.8.9', new Version('4.8.9')], ['4.8.0', new Version('4.8')], ['1.2.3-dev', new Version('1.2.3-dev')], ['1.2.3+abc', new Version('1.2.3+abc')] ]; } public function nonCompliantVersionProvider() { return [ ['1.0.2', new Version('1.0.3')], ['4.8.9', new Version('4.7.9')], ['4.8', new Version('4.8.5')], ['1.2.3+abc', new Version('1.2.3+def')] ]; } /** * @dataProvider compliantVersionProvider * * @param string $constraintValue */ public function testReturnsTrueForCompliantVersion($constraintValue, Version $version): void { $constraint = new ExactVersionConstraint($constraintValue); $this->assertTrue($constraint->complies($version)); } /** * @dataProvider nonCompliantVersionProvider * * @param string $constraintValue */ public function testReturnsFalseForNonCompliantVersion($constraintValue, Version $version): void { $constraint = new ExactVersionConstraint($constraintValue); $this->assertFalse($constraint->complies($version)); } } ================================================ FILE: tests/Unit/GreaterThanOrEqualToVersionConstraintTest.php ================================================ , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; use PHPUnit\Framework\TestCase; /** * @covers \PharIo\Version\GreaterThanOrEqualToVersionConstraint */ class GreaterThanOrEqualToVersionConstraintTest extends TestCase { public function versionProvider() { return [ // compliant versions [new Version('1.0.2'), new Version('1.0.2'), true], [new Version('1.0.2'), new Version('1.0.3'), true], [new Version('1.0.2'), new Version('1.1.1'), true], [new Version('1.0.2'), new Version('2.0.0'), true], [new Version('1.0.2'), new Version('1.0.3'), true], // non-compliant versions [new Version('1.0.2'), new Version('1.0.1'), false], [new Version('1.9.8'), new Version('0.9.9'), false], [new Version('2.3.1'), new Version('2.2.3'), false], [new Version('3.0.2'), new Version('2.9.9'), false], ]; } /** * @dataProvider versionProvider * * @param bool $expectedResult */ public function testReturnsTrueForCompliantVersions(Version $constraintVersion, Version $version, $expectedResult): void { $constraint = new GreaterThanOrEqualToVersionConstraint('foo', $constraintVersion); $this->assertSame($expectedResult, $constraint->complies($version)); } } ================================================ FILE: tests/Unit/OrVersionConstraintGroupTest.php ================================================ , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; use PHPUnit\Framework\TestCase; /** * @covers \PharIo\Version\OrVersionConstraintGroup */ class OrVersionConstraintGroupTest extends TestCase { public function testReturnsTrueIfOneConstraintReturnsFalse(): void { $firstConstraint = $this->createMock(VersionConstraint::class); $secondConstraint = $this->createMock(VersionConstraint::class); $firstConstraint->expects($this->once()) ->method('complies') ->will($this->returnValue(false)); $secondConstraint->expects($this->once()) ->method('complies') ->will($this->returnValue(true)); $group = new OrVersionConstraintGroup('foo', [$firstConstraint, $secondConstraint]); $this->assertTrue($group->complies(new Version('1.0.0'))); } public function testReturnsTrueIfAllConstraintsReturnsTrue(): void { $firstConstraint = $this->createMock(VersionConstraint::class); $secondConstraint = $this->createMock(VersionConstraint::class); $firstConstraint->expects($this->once()) ->method('complies') ->will($this->returnValue(true)); $group = new OrVersionConstraintGroup('foo', [$firstConstraint, $secondConstraint]); $this->assertTrue($group->complies(new Version('1.0.0'))); } public function testReturnsFalseIfAllConstraintsReturnsFalse(): void { $firstConstraint = $this->createMock(VersionConstraint::class); $secondConstraint = $this->createMock(VersionConstraint::class); $firstConstraint->expects($this->once()) ->method('complies') ->will($this->returnValue(false)); $secondConstraint->expects($this->once()) ->method('complies') ->will($this->returnValue(false)); $group = new OrVersionConstraintGroup('foo', [$firstConstraint, $secondConstraint]); $this->assertFalse($group->complies(new Version('1.0.0'))); } } ================================================ FILE: tests/Unit/PreReleaseSuffixTest.php ================================================ assertSame($expectedResult, $leftSuffix->isGreaterThan($rightSuffix)); } public function greaterThanProvider() { return [ ['alpha1', 'alpha2', false], ['alpha2', 'alpha1', true], ['beta1', 'alpha3', true], ['b1', 'alpha3', true], ['b1', 'a3', true], ['dev1', 'alpha2', false], ['dev1', 'alpha2', false], ['alpha2', 'dev5', true], ['rc1', 'beta2', true], ['patch5', 'rc7', true], ['alpha1', 'alpha.2', false], ['alpha.3', 'alpha2', true], ['alpha.3', 'alpha.2', true], ]; } /** * @dataProvider suffixProvider */ public function testParsedValue(string $suffix): void { $prs = new PreReleaseSuffix($suffix); $this->assertEquals($suffix, $prs->asString()); } public function suffixProvider() { return [ ['alpha1'], ['beta1'], ['b1'], ['dev1'], ['rc1'], ['patch5'], ['alpha.1'], ['beta.1'], ['b.1'], ['dev.1'], ['rc.1'], ['patch.5'] ]; } public function testLabelCanBeRetrieved(): void { $this->assertSame('rc', (new PreReleaseSuffix('rc1'))->getValue()); } public function testCreatingWithUnsupportedLabelTypeThrowsException(): void { $this->expectException(InvalidPreReleaseSuffixException::class); (new PreReleaseSuffix('foo')); } } ================================================ FILE: tests/Unit/SpecificMajorAndMinorVersionConstraintTest.php ================================================ , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; use PHPUnit\Framework\TestCase; /** * @covers \PharIo\Version\SpecificMajorAndMinorVersionConstraint */ class SpecificMajorAndMinorVersionConstraintTest extends TestCase { public function versionProvider() { return [ // compliant versions [1, 0, new Version('1.0.2'), true], [1, 0, new Version('1.0.3'), true], [1, 1, new Version('1.1.1'), true], // non-compliant versions [2, 9, new Version('0.9.9'), false], [3, 2, new Version('2.2.3'), false], [2, 8, new Version('2.9.9'), false], ]; } /** * @dataProvider versionProvider * * @param int $major * @param int $minor * @param bool $expectedResult */ public function testReturnsTrueForCompliantVersions($major, $minor, Version $version, $expectedResult): void { $constraint = new SpecificMajorAndMinorVersionConstraint('foo', $major, $minor); $this->assertSame($expectedResult, $constraint->complies($version)); } } ================================================ FILE: tests/Unit/SpecificMajorVersionConstraintTest.php ================================================ , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; use PHPUnit\Framework\TestCase; /** * @covers \PharIo\Version\SpecificMajorVersionConstraint */ class SpecificMajorVersionConstraintTest extends TestCase { public function versionProvider() { return [ // compliant versions [1, new Version('1.0.2'), true], [1, new Version('1.0.3'), true], [1, new Version('1.1.1'), true], // non-compliant versions [2, new Version('0.9.9'), false], [3, new Version('2.2.3'), false], [3, new Version('2.9.9'), false], ]; } /** * @dataProvider versionProvider * * @param int $major * @param bool $expectedResult */ public function testReturnsTrueForCompliantVersions($major, Version $version, $expectedResult): void { $constraint = new SpecificMajorVersionConstraint('foo', $major); $this->assertSame($expectedResult, $constraint->complies($version)); } } ================================================ FILE: tests/Unit/VersionTest.php ================================================ , Sebastian Heuer , Sebastian Bergmann * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PharIo\Version; use PHPUnit\Framework\TestCase; /** * @covers \PharIo\Version\Version */ class VersionTest extends TestCase { /** * @dataProvider versionProvider * * @param string $versionString * @param string $expectedMajor * @param string $expectedMinor * @param string $expectedPatch * @param string $expectedPreReleaseValue * @param int $expectedReleaseCount * @param string $metaData */ public function testParsesVersionNumbers( $versionString, $expectedMajor, $expectedMinor, $expectedPatch, $expectedPreReleaseValue = '', $expectedReleaseCount = 0, $metaData = '' ): void { $version = new Version($versionString); $this->assertSame($expectedMajor, $version->getMajor()->getValue()); $this->assertSame($expectedMinor, $version->getMinor()->getValue()); $this->assertSame($expectedPatch, $version->getPatch()->getValue()); if ($expectedPreReleaseValue !== '') { $this->assertSame($expectedPreReleaseValue, $version->getPreReleaseSuffix()->getValue()); } if ($expectedReleaseCount !== 0) { $this->assertSame($expectedReleaseCount, $version->getPreReleaseSuffix()->getNumber()); } if ($metaData !== '') { $this->assertSame($metaData, $version->getBuildMetaData()->asString()); } } public function versionProvider() { return [ ['0.0.1', 0, 0, 1], ['0.1.2', 0, 1, 2], ['1.0.0-alpha', 1, 0, 0, 'alpha'], ['3.4.12-dev3', 3, 4, 12, 'dev', 3], ['1.2.3-beta.2', 1, 2, 3, 'beta', 2], ['v1.2.3-rc', 1, 2, 3, 'rc'], ['v1.2.3-rc1', 1, 2, 3, 'rc', 1], ['0.0.1-dev+ABC', 0, 0, 1, 'dev', 0, 'ABC'], ['0.0.1+git-15a90844ad40f127afd244c0cad228de2a80052a', 0, 0, 1, '', 0, 'git-15a90844ad40f127afd244c0cad228de2a80052a'] ]; } /** * @dataProvider versionStringProvider */ public function testOrigionalStringReturnsExceptedVersionString(string $input): void { $this->assertEquals( (new Version($input))->getOriginalString(), $input ); } /** * @dataProvider versionStringProvider */ public function testAsStringReturnsExceptedVersionString(string $input, string $excepted): void { $this->assertEquals( (new Version($input))->getVersionString(), $excepted ); } /** * @dataProvider versionGreaterThanProvider * * @param bool $expectedResult */ public function testIsGreaterThan(Version $versionA, Version $versionB, $expectedResult): void { $this->assertSame($expectedResult, $versionA->isGreaterThan($versionB)); } public function versionGreaterThanProvider(): array { return [ [new Version('1.0.0'), new Version('1.0.1'), false], [new Version('1.0.1'), new Version('1.0.0'), true], [new Version('1.1.0'), new Version('1.0.1'), true], [new Version('1.1.0'), new Version('2.0.1'), false], [new Version('1.1.0'), new Version('1.1.0'), false], [new Version('2.5.8'), new Version('1.6.8'), true], [new Version('2.5.8'), new Version('2.6.8'), false], [new Version('2.5.8'), new Version('3.1.2'), false], [new Version('3.0.0-alpha1'), new Version('3.0.0-alpha2'), false], [new Version('3.0.0-alpha2'), new Version('3.0.0-alpha1'), true], [new Version('3.0.0-alpha.1'), new Version('3.0.0'), false], [new Version('3.0.0'), new Version('3.0.0-alpha.1'), true], ]; } /** * @dataProvider invalidVersionStringProvider * * @param string $versionString */ public function testThrowsExceptionIfVersionStringDoesNotFollowSemVer($versionString): void { $this->expectException(InvalidVersionException::class); new Version($versionString); } public function invalidVersionStringProvider(): array { return [ ['foo'], ['1.2.3.4'], ['1.0.0-x.7.z.92'] ]; } public function versionStringProvider() { return [ ['0.0.1', '0.0.1'], ['0.1.0', '0.1.0'], ['1.0.0-alpha', '1.0.0-alpha'], ['3.4.12-dev3', '3.4.12-dev3'], ['1.2.3-beta.2', '1.2.3-beta.2'], ['v0.0.1', '0.0.1'], ['v0.1.0', '0.1.0'], ['v1.0.0-alpha', '1.0.0-alpha'], ['v3.4.12-dev3', '3.4.12-dev3'], ['v1.2.3-beta.2', '1.2.3-beta.2'], ['0.1', '0.1.0'], ['v0.1', '0.1.0'], ['1', '1.0.0'] ]; } public function testIdenticalVersionsAreConsideredEqual(): void { $a = new Version('1.0.0-rc1'); $b = new Version('1.0.0-rc1'); $this->assertTrue($a->equals($b)); } public function testNonIdenticalVersionsAreNotConsideredEqual(): void { $a = new Version('1.0.0-rc1'); $b = new Version('1.0.0-rc2'); $this->assertFalse($a->equals($b)); } public function testIdenticalVersionsWithBuildMetaDataAreConsideredEqual(): void { $a = new Version('1.0.0-rc1+abc'); $b = new Version('1.0.0-rc1+abc'); $this->assertTrue($a->equals($b)); } public function testIdenticalVersionsWithOnlyOneHavingBuildMetaDataAreNotConsideredEqual(): void { $a = new Version('1.0.0-rc1+abc'); $b = new Version('1.0.0-rc1'); $this->assertFalse($a->equals($b)); } public function testIdenticalVersionsWithDifferingBuildMetaDataAreNotConsideredEqual(): void { $a = new Version('1.0.0-rc1+abc'); $b = new Version('1.0.0-rc1+def'); $this->assertFalse($a->equals($b)); } public function testGetPreReleaseSuffixThrowsExceptionWhenNoneIsSet(): void { $this->expectException(NoPreReleaseSuffixException::class); (new Version('1.2.3'))->getPreReleaseSuffix(); } public function testGetBuildMetadataThrowsExceptionWhenNoneIsSet(): void { $this->expectException(NoBuildMetaDataException::class); (new Version('1.2.3'))->getBuildMetaData(); } public function testHasBuildMetadataReturnsFalseWhenNoneIsSet(): void { $this->assertFalse((new Version('1.2.3'))->hasBuildMetaData()); } public function testBuildMetadataCanBeRetreived(): void { $this->assertSame('test', (new Version('1.2.3+test'))->getBuildMetaData()->asString()); } }