diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8c90d13..8d0c284 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,10 +12,12 @@ For a full diff see [`64ced12...main`][64ced12...main].
- Added `Version` as a value object ([#1]), by [@localheinz]
- Added `Major` as a value object ([#3]), by [@localheinz]
+- Added `Minor` as a value object ([#4]), by [@localheinz]
[64ced12...main]: https://github.com/ergebnis/version/compare/64ced12...main
[#1]: https://github.com/ergebnis/version/pull/1
[#3]: https://github.com/ergebnis/version/pull/3
+[#4]: https://github.com/ergebnis/version/pull/4
[@localheinz]: https://github.com/localheinz
diff --git a/README.md b/README.md
index b0a2de9..f8007c2 100644
--- a/README.md
+++ b/README.md
@@ -38,6 +38,7 @@ $version = Version\Version::fromString('1.2.3');
echo $version->toString(); // 1.2.3
echo $version->major()->toString(); // 1
+echo $version->minor()->toString(); // 2
```
### Compare a `Version` with another `Version`
@@ -90,6 +91,39 @@ $one->equals($three); // false
$one->equals($two); // true
```
+### Create a `Minor` from a `string`
+
+```php
+toString(); // 1
+```
+
+### Compare a `Minor` with another `Minor`
+
+```php
+equals($two); // true
+$one->equals($three); // false
+
+$one->equals($two); // true
+```
+
## Changelog
The maintainers of this project record notable changes to this project in a [changelog](CHANGELOG.md).
diff --git a/psalm-baseline.xml b/psalm-baseline.xml
index b132131..441f0f0 100644
--- a/psalm-baseline.xml
+++ b/psalm-baseline.xml
@@ -6,6 +6,12 @@
provideValidValue
+
+
+ provideInvalidValue
+ provideValidValue
+
+
provideInvalidValue
diff --git a/src/Exception/InvalidMinor.php b/src/Exception/InvalidMinor.php
new file mode 100644
index 0000000..a5cac14
--- /dev/null
+++ b/src/Exception/InvalidMinor.php
@@ -0,0 +1,25 @@
+0|[1-9]\d*)$/';
+
+ private function __construct(private readonly string $value)
+ {
+ }
+
+ /**
+ * @throws Exception\InvalidMinor
+ */
+ public static function fromString(string $value): self
+ {
+ if (1 !== \preg_match(self::REGEX, $value)) {
+ throw Exception\InvalidMinor::fromString($value);
+ }
+
+ return new self($value);
+ }
+
+ public function toString(): string
+ {
+ return $this->value;
+ }
+
+ public function equals(self $other): bool
+ {
+ return $this->value === $other->value;
+ }
+}
diff --git a/src/Version.php b/src/Version.php
index 9bdc4d3..3b124e4 100644
--- a/src/Version.php
+++ b/src/Version.php
@@ -24,6 +24,7 @@ final class Version
private function __construct(
private readonly string $value,
private readonly Major $major,
+ private readonly Minor $minor,
) {
}
@@ -39,6 +40,7 @@ public static function fromString(string $value): self
return new self(
$value,
Major::fromString($matches['major']),
+ Minor::fromString($matches['minor']),
);
}
@@ -56,4 +58,9 @@ public function major(): Major
{
return $this->major;
}
+
+ public function minor(): Minor
+ {
+ return $this->minor;
+ }
}
diff --git a/test/Unit/Exception/InvalidMinorTest.php b/test/Unit/Exception/InvalidMinorTest.php
new file mode 100644
index 0000000..9c1b85e
--- /dev/null
+++ b/test/Unit/Exception/InvalidMinorTest.php
@@ -0,0 +1,38 @@
+word();
+
+ $exception = Exception\InvalidMinor::fromString($value);
+
+ $message = \sprintf(
+ 'Value "%s" does not appear to be valid.',
+ $value,
+ );
+
+ self::assertSame($message, $exception->getMessage());
+ }
+}
diff --git a/test/Unit/MinorTest.php b/test/Unit/MinorTest.php
new file mode 100644
index 0000000..e010d3c
--- /dev/null
+++ b/test/Unit/MinorTest.php
@@ -0,0 +1,107 @@
+expectException(Exception\InvalidMinor::class);
+
+ Minor::fromString($value);
+ }
+
+ /**
+ * @see https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
+ * @see https://regex101.com/r/Ly7O1x/3/
+ *
+ * @return Generator
+ */
+ public static function provideInvalidValue(): Generator
+ {
+ $faker = self::faker();
+
+ $values = [
+ 'leading-zero' => \sprintf(
+ '0%d',
+ $faker->numberBetween(1),
+ ),
+ 'word' => $faker->word(),
+ ];
+
+ foreach ($values as $value) {
+ yield $value => [
+ $value,
+ ];
+ }
+ }
+
+ #[Framework\Attributes\DataProvider('provideValidValue')]
+ public function testFromStringReturnsMinor(string $value): void
+ {
+ $minor = Minor::fromString($value);
+
+ self::assertSame($value, $minor->toString());
+ }
+
+ /**
+ * @see https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
+ * @see https://regex101.com/r/Ly7O1x/3/
+ *
+ * @return Generator
+ */
+ public static function provideValidValue(): Generator
+ {
+ $values = [
+ 'zero' => '0',
+ 'one' => '1',
+ 'greater-than-one' => (string) self::faker()->numberBetween(2),
+ ];
+
+ foreach ($values as $key => $value) {
+ yield $key => [
+ $value,
+ ];
+ }
+ }
+
+ public function testEqualsReturnsFalseWhenValuesAreDifferent(): void
+ {
+ $faker = self::faker()->unique();
+
+ $one = Minor::fromString((string) $faker->numberBetween(0));
+ $two = Minor::fromString((string) $faker->numberBetween(0));
+
+ self::assertFalse($one->equals($two));
+ }
+
+ public function testEqualsReturnsTrueWhenValueIsSame(): void
+ {
+ $value = (string) self::faker()->numberBetween(0);
+
+ $one = Minor::fromString($value);
+ $two = Minor::fromString($value);
+
+ self::assertTrue($one->equals($two));
+ }
+}
diff --git a/test/Unit/VersionTest.php b/test/Unit/VersionTest.php
index 970d351..04eb50a 100644
--- a/test/Unit/VersionTest.php
+++ b/test/Unit/VersionTest.php
@@ -15,6 +15,7 @@
use Ergebnis\Version\Exception;
use Ergebnis\Version\Major;
+use Ergebnis\Version\Minor;
use Ergebnis\Version\Test;
use Ergebnis\Version\Version;
use PHPUnit\Framework;
@@ -22,6 +23,7 @@
#[Framework\Attributes\CoversClass(Version::class)]
#[Framework\Attributes\UsesClass(Exception\InvalidVersion::class)]
#[Framework\Attributes\UsesClass(Major::class)]
+#[Framework\Attributes\UsesClass(Minor::class)]
final class VersionTest extends Framework\TestCase
{
use Test\Util\Helper;
@@ -95,122 +97,156 @@ public static function provideInvalidValue(): \Generator
public function testFromStringReturnsVersion(
string $value,
Major $major,
+ Minor $minor,
): void {
$version = Version::fromString($value);
self::assertSame($value, $version->toString());
self::assertEquals($major, $version->major());
+ self::assertEquals($minor, $version->minor());
}
/**
* @see https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
* @see https://regex101.com/r/Ly7O1x/3/
*
- * @return \Generator
+ * @return \Generator
*/
public static function provideValidValue(): \Generator
{
$values = [
'0.0.4' => [
Major::fromString('0'),
+ Minor::fromString('0'),
],
'1.2.3' => [
Major::fromString('1'),
+ Minor::fromString('2'),
],
'10.20.30' => [
Major::fromString('10'),
+ Minor::fromString('20'),
],
'1.1.2-prerelease+meta' => [
Major::fromString('1'),
+ Minor::fromString('1'),
],
'1.1.2+meta' => [
Major::fromString('1'),
+ Minor::fromString('1'),
],
'1.1.2+meta-valid' => [
Major::fromString('1'),
+ Minor::fromString('1'),
],
'1.0.0-alpha' => [
Major::fromString('1'),
+ Minor::fromString('0'),
],
'1.0.0-beta' => [
Major::fromString('1'),
+ Minor::fromString('0'),
],
'1.0.0-alpha.beta' => [
Major::fromString('1'),
+ Minor::fromString('0'),
],
'1.0.0-alpha.beta.1' => [
Major::fromString('1'),
+ Minor::fromString('0'),
],
'1.0.0-alpha.1' => [
Major::fromString('1'),
+ Minor::fromString('0'),
],
'1.0.0-alpha0.valid' => [
Major::fromString('1'),
+ Minor::fromString('0'),
],
'1.0.0-alpha.0valid' => [
Major::fromString('1'),
+ Minor::fromString('0'),
],
'1.0.0-alpha-a.b-c-somethinglong+build.1-aef.1-its-okay' => [
Major::fromString('1'),
+ Minor::fromString('0'),
],
'1.0.0-rc.1+build.1' => [
Major::fromString('1'),
+ Minor::fromString('0'),
],
'2.0.0-rc.1+build.123' => [
Major::fromString('2'),
+ Minor::fromString('0'),
],
'1.2.3-beta' => [
Major::fromString('1'),
+ Minor::fromString('2'),
],
'10.2.3-DEV-SNAPSHOT' => [
Major::fromString('10'),
+ Minor::fromString('2'),
],
'1.2.3-SNAPSHOT-123' => [
Major::fromString('1'),
+ Minor::fromString('2'),
],
'1.0.0' => [
Major::fromString('1'),
+ Minor::fromString('0'),
],
'2.0.0' => [
Major::fromString('2'),
+ Minor::fromString('0'),
],
'1.1.7' => [
Major::fromString('1'),
+ Minor::fromString('1'),
],
'2.0.0+build.1848' => [
Major::fromString('2'),
+ Minor::fromString('0'),
],
'2.0.1-alpha.1227' => [
Major::fromString('2'),
+ Minor::fromString('0'),
],
'1.0.0-alpha+beta' => [
Major::fromString('1'),
+ Minor::fromString('0'),
],
'1.2.3----RC-SNAPSHOT.12.9.1--.12+788' => [
Major::fromString('1'),
+ Minor::fromString('2'),
],
'1.2.3----R-S.12.9.1--.12+meta' => [
Major::fromString('1'),
+ Minor::fromString('2'),
],
'1.2.3----RC-SNAPSHOT.12.9.1--.12' => [
Major::fromString('1'),
+ Minor::fromString('2'),
],
'1.0.0+0.build.1-rc.10000aaa-kk-0.1' => [
Major::fromString('1'),
+ Minor::fromString('0'),
],
'99999999999999999999999.999999999999999999.99999999999999999' => [
Major::fromString('99999999999999999999999'),
+ Minor::fromString('999999999999999999'),
],
'1.0.0-0A.is.legal' => [
Major::fromString('1'),
+ Minor::fromString('0'),
],
];
- foreach ($values as $value => [$major]) {
+ foreach ($values as $value => [$major, $minor]) {
yield $value => [
$value,
$major,
+ $minor,
];
}
}