Skip to content

Commit 4b8f0e1

Browse files
committed
Enhancement: Extract Version
1 parent 4ac417b commit 4b8f0e1

14 files changed

+460
-5
lines changed

include/branches.inc

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
<?php
2+
3+
require_once __DIR__ . '/../src/autoload.php';
24
include_once __DIR__ . '/releases.inc';
35
include_once __DIR__ . '/version.inc';
46

7+
use phpweb\Release;
8+
59
/* Branch overrides. For situations where we've changed the exact dates for a
610
* branch's active support and security fix EOLs, these can be reflected here.
711
*
@@ -85,13 +89,18 @@ function format_interval($from, DateTime $to) {
8589
return $eolPeriod;
8690
}
8791

88-
function version_number_to_branch(string $version): ?string {
89-
$parts = explode('.', $version);
90-
if (count($parts) > 1) {
91-
return "$parts[0].$parts[1]";
92+
function version_number_to_branch(string $value): ?string {
93+
try {
94+
$version = Release\Version::fromString($value);
95+
} catch (\InvalidArgumentException) {
96+
return null;
9297
}
9398

94-
return null;
99+
return sprintf(
100+
'%s.%s',
101+
$version->major()->toString(),
102+
$version->minor()->toString(),
103+
);
95104
}
96105

97106
function get_all_branches() {

src/Release/Major.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace phpweb\Release;
6+
7+
final readonly class Major
8+
{
9+
private function __construct(private string $value)
10+
{
11+
}
12+
13+
/**
14+
* @throws \InvalidArgumentException
15+
*/
16+
public static function fromString(string $value): self
17+
{
18+
if (1 !== preg_match('/^(0|[1-9]\d*)$/', $value)) {
19+
throw new \InvalidArgumentException(\sprintf(
20+
'Value "%s" does not appear to be a valid value for a major version.',
21+
$value
22+
));
23+
}
24+
25+
return new self($value);
26+
}
27+
28+
public function toString(): string
29+
{
30+
return $this->value;
31+
}
32+
}

src/Release/Minor.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace phpweb\Release;
6+
7+
final readonly class Minor
8+
{
9+
private function __construct(private string $value)
10+
{
11+
}
12+
13+
/**
14+
* @throws \InvalidArgumentException
15+
*/
16+
public static function fromString(string $value): self
17+
{
18+
if (1 !== preg_match('/^(0|[1-9]\d*)$/', $value)) {
19+
throw new \InvalidArgumentException(\sprintf(
20+
'Value "%s" does not appear to be a valid value for a minor version.',
21+
$value
22+
));
23+
}
24+
25+
return new self($value);
26+
}
27+
28+
public function toString(): string
29+
{
30+
return $this->value;
31+
}
32+
}

src/Release/Patch.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace phpweb\Release;
6+
7+
final readonly class Patch
8+
{
9+
private function __construct(private string $value)
10+
{
11+
}
12+
13+
/**
14+
* @throws \InvalidArgumentException
15+
*/
16+
public static function fromString(string $value): self
17+
{
18+
if (1 !== preg_match('/^(0|[1-9]\d*)$/', $value)) {
19+
throw new \InvalidArgumentException(\sprintf(
20+
'Value "%s" does not appear to be a valid value for a patch version.',
21+
$value
22+
));
23+
}
24+
25+
return new self($value);
26+
}
27+
28+
public function toString(): string
29+
{
30+
return $this->value;
31+
}
32+
}

src/Release/Version.php

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace phpweb\Release;
6+
7+
final readonly class Version
8+
{
9+
private function __construct(
10+
private Major $major,
11+
private Minor $minor,
12+
private Patch $patch,
13+
) {
14+
}
15+
16+
public static function create(
17+
Major $major,
18+
Minor $minor,
19+
Patch $patch,
20+
): self {
21+
return new self(
22+
$major,
23+
$minor,
24+
$patch,
25+
);
26+
}
27+
28+
/**
29+
* @throws \InvalidArgumentException
30+
*/
31+
public static function fromString(string $value): self
32+
{
33+
if (1 !== preg_match('/^(?P<major>(0|[1-9]\d*))\.(?P<minor>(0|[1-9]\d*))\.(?P<patch>(0|[1-9]\d*))$/', $value, $matches)) {
34+
throw new \InvalidArgumentException(\sprintf(
35+
'Value "%s" does not appear to be a valid value for a version.',
36+
$value
37+
));
38+
}
39+
40+
return new self(
41+
Major::fromString($matches['major']),
42+
Minor::fromString($matches['minor']),
43+
Patch::fromString($matches['patch']),
44+
);
45+
}
46+
47+
public function major(): Major
48+
{
49+
return $this->major;
50+
}
51+
52+
public function minor(): Minor
53+
{
54+
return $this->minor;
55+
}
56+
57+
public function patch(): Patch
58+
{
59+
return $this->patch;
60+
}
61+
62+
public function toString(): string
63+
{
64+
return sprintf(
65+
'%s.%s.%s',
66+
$this->major->toString(),
67+
$this->minor->toString(),
68+
$this->patch->toString(),
69+
);
70+
}
71+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
--TEST--
2+
Major::fromString() rejects invalid values
3+
--FILE--
4+
<?php
5+
6+
declare(strict_types=1);
7+
8+
use phpweb\Release;
9+
10+
require_once __DIR__ . '/../../../../src/autoload.php';
11+
12+
$values = [
13+
'string-blank' => ' ',
14+
'string-empty' => '',
15+
'string-leading-zero' => '01',
16+
'string-word' => 'foo',
17+
];
18+
19+
$invalidValues = array_filter($values, static function (string $value): bool {
20+
try {
21+
Release\Major::fromString($value);
22+
} catch (\InvalidArgumentException) {
23+
return true;
24+
}
25+
26+
return false;
27+
});
28+
29+
var_dump($invalidValues);
30+
?>
31+
--EXPECT--
32+
array(4) {
33+
["string-blank"]=>
34+
string(1) " "
35+
["string-empty"]=>
36+
string(0) ""
37+
["string-leading-zero"]=>
38+
string(2) "01"
39+
["string-word"]=>
40+
string(3) "foo"
41+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
Major::fromString() returns Major
3+
--FILE--
4+
<?php
5+
6+
declare(strict_types=1);
7+
8+
use phpweb\Release;
9+
10+
require_once __DIR__ . '/../../../../src/autoload.php';
11+
12+
$major = Release\Major::fromString('8');
13+
14+
var_dump($major->toString());
15+
?>
16+
--EXPECT--
17+
string(1) "8"
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
--TEST--
2+
Minor::fromString() rejects invalid values
3+
--FILE--
4+
<?php
5+
6+
declare(strict_types=1);
7+
8+
use phpweb\Release;
9+
10+
require_once __DIR__ . '/../../../../src/autoload.php';
11+
12+
$values = [
13+
'string-blank' => ' ',
14+
'string-empty' => '',
15+
'string-leading-zero' => '01',
16+
'string-word' => 'foo',
17+
];
18+
19+
$invalidValues = array_filter($values, static function (string $value): bool {
20+
try {
21+
Release\Minor::fromString($value);
22+
} catch (\InvalidArgumentException) {
23+
return true;
24+
}
25+
26+
return false;
27+
});
28+
29+
var_dump($invalidValues);
30+
?>
31+
--EXPECT--
32+
array(4) {
33+
["string-blank"]=>
34+
string(1) " "
35+
["string-empty"]=>
36+
string(0) ""
37+
["string-leading-zero"]=>
38+
string(2) "01"
39+
["string-word"]=>
40+
string(3) "foo"
41+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
Minor::fromString() returns Minor
3+
--FILE--
4+
<?php
5+
6+
declare(strict_types=1);
7+
8+
use phpweb\Release;
9+
10+
require_once __DIR__ . '/../../../../src/autoload.php';
11+
12+
$minor = Release\Minor::fromString('3');
13+
14+
var_dump($minor->toString());
15+
?>
16+
--EXPECT--
17+
string(1) "3"
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
--TEST--
2+
Patch::fromString() rejects invalid values
3+
--FILE--
4+
<?php
5+
6+
declare(strict_types=1);
7+
8+
use phpweb\Release;
9+
10+
require_once __DIR__ . '/../../../../src/autoload.php';
11+
12+
$values = [
13+
'string-blank' => ' ',
14+
'string-empty' => '',
15+
'string-leading-zero' => '01',
16+
'string-word' => 'foo',
17+
];
18+
19+
$invalidValues = array_filter($values, static function (string $value): bool {
20+
try {
21+
Release\Patch::fromString($value);
22+
} catch (\InvalidArgumentException) {
23+
return true;
24+
}
25+
26+
return false;
27+
});
28+
29+
var_dump($invalidValues);
30+
?>
31+
--EXPECT--
32+
array(4) {
33+
["string-blank"]=>
34+
string(1) " "
35+
["string-empty"]=>
36+
string(0) ""
37+
["string-leading-zero"]=>
38+
string(2) "01"
39+
["string-word"]=>
40+
string(3) "foo"
41+
}

0 commit comments

Comments
 (0)