Completed
Push — master ( 6ae487...78e9d4 )
by Nikola
01:09
created

Version::fromString()   A

Complexity

Conditions 6
Paths 2

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 14
ccs 9
cts 9
cp 1
rs 9.2222
c 0
b 0
f 0
cc 6
nc 2
nop 1
crap 6
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Version;
6
7
use JsonSerializable;
8
use Version\Assert\VersionAssert;
9
use Version\Extension\Build;
10
use Version\Exception\InvalidVersionString;
11
use Version\Comparison\Comparator;
12
use Version\Comparison\SemverComparator;
13
use Version\Comparison\Constraint\Constraint;
14
use Version\Extension\PreRelease;
15
16
class Version implements JsonSerializable
17
{
18
    public const REGEX = '#^(v|release\-)?(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:\-(?P<preRelease>(?:0|[1-9]\d*|\d*[a-zA-Z\-][0-9a-zA-Z\-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z\-][0-9a-zA-Z\-]*))*))?(?:\+(?P<build>[0-9a-zA-Z\-]+(?:\.[0-9a-zA-Z\-]+)*))?$#';
19
20
    protected $major;
21
    protected $minor;
22
    protected $patch;
23
    protected $preRelease;
24
    protected $build;
25
26
    protected static $comparator;
27
28 79
    final protected function __construct(int $major, int $minor, int $patch, PreRelease $preRelease = null, Build $build = null)
29
    {
30 79
        VersionAssert::that($major)->greaterOrEqualThan(0, 'Major version must be positive integer');
31 78
        VersionAssert::that($minor)->greaterOrEqualThan(0, 'Minor version must be positive integer');
32 77
        VersionAssert::that($patch)->greaterOrEqualThan(0, 'Patch version must be positive integer');
33
34 76
        $this->major = $major;
35 76
        $this->minor = $minor;
36 76
        $this->patch = $patch;
37 76
        $this->preRelease = $preRelease;
38 76
        $this->build = $build;
39 76
    }
40
41 28
    public static function from(int $major, int $minor = 0, int $patch = 0, PreRelease $preRelease = null, Build $build = null)
42
    {
43 28
        return new static($major, $minor, $patch, $preRelease, $build);
44
    }
45
46
    /**
47
     * @throws InvalidVersionString
48
     */
49 77
    public static function fromString(string $versionString)
50
    {
51 77
        if (!preg_match(self::REGEX, $versionString, $parts)) {
52 4
            throw InvalidVersionString::notParsable($versionString);
53
        }
54
55 73
        return new static(
56 73
            (int) $parts['major'],
57 73
            (int) $parts['minor'],
58 73
            (int) $parts['patch'],
59 73
            (isset($parts['preRelease']) && '' !== $parts['preRelease']) ? PreRelease::fromString($parts['preRelease']) : null,
60 73
            (isset($parts['build']) && '' !== $parts['build']) ? Build::fromString($parts['build']) : null
61
        );
62
    }
63
64 57
    public function getMajor(): int
65
    {
66 57
        return $this->major;
67
    }
68
69 53
    public function getMinor(): int
70
    {
71 53
        return $this->minor;
72
    }
73
74 49
    public function getPatch(): int
75
    {
76 49
        return $this->patch;
77
    }
78
79 18
    public function getPreRelease(): ?PreRelease
80
    {
81 18
        return $this->preRelease;
82
    }
83
84 6
    public function getBuild(): ?Build
85
    {
86 6
        return $this->build;
87
    }
88
89
    /**
90
     * @param Version|string $version
91
     * @return bool
92
     */
93 6
    public function isEqualTo($version): bool
94
    {
95 6
        return $this->compareTo($version) === 0;
96
    }
97
98
    /**
99
     * @param Version|string $version
100
     * @return bool
101
     */
102 1
    public function isNotEqualTo($version): bool
103
    {
104 1
        return !$this->isEqualTo($version);
105
    }
106
107
    /**
108
     * @param Version|string $version
109
     * @return bool
110
     */
111 3
    public function isGreaterThan($version): bool
112
    {
113 3
        return $this->compareTo($version) > 0;
114
    }
115
116
    /**
117
     * @param Version|string $version
118
     * @return bool
119
     */
120 4
    public function isGreaterOrEqualTo($version): bool
121
    {
122 4
        return $this->compareTo($version) >= 0;
123
    }
124
125
    /**
126
     * @param Version|string $version
127
     * @return bool
128
     */
129 3
    public function isLessThan($version): bool
130
    {
131 3
        return $this->compareTo($version) < 0;
132
    }
133
134
    /**
135
     * @param Version|string $version
136
     * @return bool
137
     */
138 2
    public function isLessOrEqualTo($version): bool
139
    {
140 2
        return $this->compareTo($version) <= 0;
141
    }
142
143
    /**
144
     * @param Version|string $version
145
     * @return int (1 if $this > $version, -1 if $this < $version, 0 if equal)
146
     */
147 23
    public function compareTo($version): int
148
    {
149 23
        if (is_string($version)) {
150 7
            $version = static::fromString($version);
151
        }
152
153 23
        return $this->getComparator()->compare($this, $version);
154
    }
155
156 2
    public function isMajorRelease(): bool
157
    {
158 2
        return $this->major > 0 && $this->minor === 0 && $this->patch === 0;
159
    }
160
161 1
    public function isMinorRelease(): bool
162
    {
163 1
        return $this->minor > 0 && $this->patch === 0;
164
    }
165
166 1
    public function isPatchRelease(): bool
167
    {
168 1
        return $this->patch > 0;
169
    }
170
171 63
    public function isPreRelease(): bool
172
    {
173 63
        return null !== $this->preRelease;
174
    }
175
176 42
    public function hasBuild(): bool
177
    {
178 42
        return null !== $this->build;
179
    }
180
181 1
    public function incrementMajor(): Version
182
    {
183 1
        return new static($this->major + 1, 0, 0);
184
    }
185
186 2
    public function incrementMinor(): Version
187
    {
188 2
        return new static($this->major, $this->minor + 1, 0);
189
    }
190
191 1
    public function incrementPatch(): Version
192
    {
193 1
        return new static($this->major, $this->minor, $this->patch + 1);
194
    }
195
196
    /**
197
     * @param PreRelease|string|null $preRelease
198
     * @return Version
199
     */
200 2
    public function withPreRelease($preRelease): Version
201
    {
202 2
        if (is_string($preRelease)) {
203 2
            $preRelease = PreRelease::fromString($preRelease);
204
        }
205
206 2
        return new static($this->major, $this->minor, $this->patch, $preRelease);
207
    }
208
209
    /**
210
     * @param Build|string|null $build
211
     * @return Version
212
     */
213 1
    public function withBuild($build): Version
214
    {
215 1
        if (is_string($build)) {
216 1
            $build = Build::fromString($build);
217
        }
218
219 1
        return new static($this->major, $this->minor, $this->patch, $this->preRelease, $build);
220
    }
221
222 2
    public function matches(Constraint $constraint): bool
223
    {
224 2
        return $constraint->assert($this);
225
    }
226
227 14
    public function toString(): string
228
    {
229
        return
230 14
            $this->major
231 14
            . '.' . $this->minor
232 14
            . '.' . $this->patch
233 14
            . ($this->isPreRelease() ? '-' . $this->preRelease->toString() : '')
234 14
            . ($this->hasBuild() ? '+' . $this->build->toString() : '')
235
        ;
236
    }
237
238
    public function __toString(): string
239
    {
240
        return $this->toString();
241
    }
242
243 4
    public function jsonSerialize(): string
244
    {
245 4
        return $this->toString();
246
    }
247
248 4
    public function toArray(): array
249
    {
250
        return [
251 4
            'major' => $this->major,
252 4
            'minor' => $this->minor,
253 4
            'patch' => $this->patch,
254 4
            'preRelease' => $this->isPreRelease() ? $this->preRelease->getIdentifiers() : null,
255 4
            'build' => $this->hasBuild() ? $this->build->getIdentifiers() : null,
256
        ];
257
    }
258
259 1
    public static function setComparator(?Comparator $comparator): void
260
    {
261 1
        static::$comparator = $comparator;
262 1
    }
263
264 23
    protected function getComparator(): Comparator
265
    {
266 23
        if (null === static::$comparator) {
267 1
            static::$comparator = new SemverComparator();
268
        }
269
270 23
        return static::$comparator;
271
    }
272
}
273