Skip to content

Commit 63570a5

Browse files
committed
Improvements
1 parent cc66b02 commit 63570a5

File tree

5 files changed

+268
-105
lines changed

5 files changed

+268
-105
lines changed

src/PreRelease.php

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
<?php
2+
3+
namespace z4kn4fein\SemVer;
4+
5+
class PreRelease
6+
{
7+
/** @var array */
8+
private $preReleaseParts;
9+
10+
/**
11+
* @return PreRelease The incremented prerelease
12+
*/
13+
public function increment()
14+
{
15+
$result = $this->copy();
16+
$lastNumericIndex = 0;
17+
foreach ($result->preReleaseParts as $key => $part) {
18+
if (is_numeric($part)) {
19+
$lastNumericIndex = $key;
20+
}
21+
}
22+
23+
if ($lastNumericIndex != 0) {
24+
$result->preReleaseParts[$lastNumericIndex] = intval($result->preReleaseParts[$lastNumericIndex]) + 1;
25+
} else {
26+
$result->preReleaseParts[] = 0;
27+
}
28+
29+
return $result;
30+
}
31+
32+
/**
33+
* @return string The string representation of the prerelease.
34+
*/
35+
public function __toString()
36+
{
37+
return implode('.', $this->preReleaseParts);
38+
}
39+
40+
private function copy()
41+
{
42+
$result = new PreRelease();
43+
$result->preReleaseParts = $this->preReleaseParts;
44+
return $result;
45+
}
46+
47+
/**
48+
* @throws VersionFormatException When the $preReleaseString is invalid.
49+
*/
50+
private function validate()
51+
{
52+
foreach ($this->preReleaseParts as $part) {
53+
if ($this->hasOnlyNumbers($part)) {
54+
if (strlen($part) > 1 && $part[0] == "0") {
55+
throw new VersionFormatException(sprintf("The prerelease part '%s' is numeric but contains a leading zero.", $part));
56+
} else {
57+
continue;
58+
}
59+
}
60+
61+
if (!$this->hasOnlyAlphanumericsAndHyphen($part)) {
62+
throw new VersionFormatException(sprintf("The prerelease part '%s' contains invalid character.", $part));
63+
}
64+
}
65+
}
66+
67+
/**
68+
* @param $part string part to check.
69+
* @return bool True when the part is containing only numbers.
70+
*/
71+
private function hasOnlyNumbers($part)
72+
{
73+
return !preg_match("/[^0-9]/", $part);
74+
}
75+
76+
/**
77+
* @param $part string The part to check.
78+
* @return bool True when the part is only containing alphanumerics.
79+
*/
80+
private function hasOnlyAlphanumericsAndHyphen($part)
81+
{
82+
return !preg_match("/[^0-9A-Za-z-]/", $part);
83+
}
84+
85+
/**
86+
* @param $preReleaseString string The prerelease string.
87+
* @return PreRelease The parsed prerelease part.
88+
* @throws VersionFormatException When the given prerelease string is invalid.
89+
*/
90+
public static function parse($preReleaseString)
91+
{
92+
$preReleaseString = trim($preReleaseString);
93+
if ($preReleaseString == null || $preReleaseString == "") {
94+
throw new VersionFormatException("preReleaseString cannot be empty.");
95+
}
96+
97+
$preRelease = new PreRelease();
98+
99+
$preRelease->preReleaseParts = explode('.', $preReleaseString);
100+
$preRelease->validate();
101+
102+
return $preRelease;
103+
}
104+
105+
/**
106+
* @param $p1 string|PreRelease The left side of the comparison.
107+
* @param $p2 string|PreRelease The right side of the comparison.
108+
* @return int -1 when $p1 < $p2, 0 when $p1 == $p2, 1 when $p1 > $p2.
109+
* @throws VersionFormatException When the given prerelease values are invalid.
110+
*/
111+
public static function compare($p1, $p2)
112+
{
113+
if (!$p1 instanceof PreRelease) {
114+
$p1 = self::parse($p1);
115+
}
116+
117+
if (!$p2 instanceof PreRelease) {
118+
$p2 = self::parse($p2);
119+
}
120+
121+
$v1Size = count($p1->preReleaseParts);
122+
$v2Size = count($p2->preReleaseParts);
123+
124+
$count = $v1Size > $v2Size ? $v2Size : $v1Size;
125+
126+
for ($i = 0; $i < $count; $i++) {
127+
$part = self::comparePart($p1->preReleaseParts[$i], $p2->preReleaseParts[$i]);
128+
if ($part != 0) {
129+
return $part;
130+
}
131+
}
132+
133+
return Utils::comparePrimitive($v1Size, $v2Size);
134+
}
135+
136+
/**
137+
* @param $a mixed The left side of the comparison.
138+
* @param $b mixed The right side of the comparison.
139+
* @return int -1 when $a < $b, 0 when $a == $b, 1 when $v1 > $b.
140+
*/
141+
private static function comparePart($a, $b)
142+
{
143+
if (is_numeric($a) && !is_numeric($b)) {
144+
return -1;
145+
}
146+
147+
if (!is_numeric($a) && is_numeric($b)) {
148+
return 1;
149+
}
150+
151+
return is_numeric($a) && is_numeric($b)
152+
? Utils::comparePrimitive(intval($a), intval($b))
153+
: Utils::comparePrimitive($a, $b);
154+
}
155+
}

src/Utils.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
namespace z4kn4fein\SemVer;
4+
5+
class Utils
6+
{
7+
/**
8+
* @param $a int|string The left side of the comparison.
9+
* @param $b int|string The right side of the comparison.
10+
* @return int -1 when $a < $b, 0 when $a == $b, 1 when $a > $b.
11+
*/
12+
public static function comparePrimitive($a, $b)
13+
{
14+
if ($a != $b) {
15+
return $a < $b ? -1 : 1;
16+
}
17+
18+
return 0;
19+
}
20+
}

0 commit comments

Comments
 (0)