Completed
Push — master ( ef0fc3...b41bb0 )
by Nikola
01:15
created

Version::from()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 5
crap 1
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\Extension\NoBuild;
11
use Version\Extension\NoPreRelease;
12
use Version\Exception\InvalidVersionString;
13
use Version\Comparison\Comparator;
14
use Version\Comparison\SemverComparator;
15
use Version\Comparison\Constraint\Constraint;
16
use Version\Extension\PreRelease;
17
18
class Version implements JsonSerializable
19
{
20
    /** @var int */
21
    protected $major;
22
23
    /** @var int */
24
    protected $minor;
25
26
    /**  @var int */
27
    protected $patch;
28
29
    /** @var PreRelease */
30
    protected $preRelease;
31
32
    /** @var Build */
33
    protected $build;
34
35
    /** @var Comparator|null */
36
    protected static $comparator;
37
38 82
    protected function __construct(int $major, int $minor, int $patch, PreRelease $preRelease, Build $build)
39
    {
40 82
        VersionAssert::that($major)->greaterOrEqualThan(0, 'Major version must be positive integer');
41 81
        VersionAssert::that($minor)->greaterOrEqualThan(0, 'Minor version must be positive integer');
42 80
        VersionAssert::that($patch)->greaterOrEqualThan(0, 'Patch version must be positive integer');
43
44 79
        $this->major = $major;
45 79
        $this->minor = $minor;
46 79
        $this->patch = $patch;
47 79
        $this->preRelease = $preRelease;
48 79
        $this->build = $build;
49 79
    }
50
51 82
    public static function from(int $major, int $minor = 0, int $patch = 0, PreRelease $preRelease = null, Build $build = null): Version
52
    {
53 82
        return new static($major, $minor, $patch, $preRelease ?? new NoPreRelease(), $build ?? new NoBuild());
54
    }
55
56
    /**
57
     * @param string $versionString
58
     *
59
     * @return Version
60
     * @throws InvalidVersionString
61
     *
62
     */
63 80
    public static function fromString(string $versionString): Version
64
    {
65 80
        if (!preg_match(
66
            '#^'
67
            . '(v|release\-)?'
68
            . '(?P<core>(?:[0-9]|[1-9][0-9]+)(?:\.(?:[0-9]|[1-9][0-9]+)){2})'
69
            . '(?:\-(?P<preRelease>[0-9A-Za-z\-\.]+))?'
70
            . '(?:\+(?P<build>[0-9A-Za-z\-\.]+))?'
71 80
            . '$#',
72 80
            $versionString,
73 80
            $parts
74
        )) {
75 5
            throw InvalidVersionString::notParsable($versionString);
76
        }
77
78 76
        [$major, $minor, $patch] = explode('.', $parts['core']);
0 ignored issues
show
Bug introduced by
The variable $major does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $minor does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $patch does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
79 76
        $preRelease = !empty($parts['preRelease']) ? PreRelease::fromIdentifiersString($parts['preRelease']) : new NoPreRelease();
80 76
        $build = !empty($parts['build']) ? Build::fromIdentifiersString($parts['build']) : new NoBuild();
81
82 76
        return static::from((int) $major, (int) $minor, (int) $patch, $preRelease, $build);
83
    }
84
85 60
    public function getMajor(): int
86
    {
87 60
        return $this->major;
88
    }
89
90 55
    public function getMinor(): int
91
    {
92 55
        return $this->minor;
93
    }
94
95 51
    public function getPatch(): int
96
    {
97 51
        return $this->patch;
98
    }
99
100 48
    public function getPreRelease(): PreRelease
101
    {
102 48
        return $this->preRelease;
103
    }
104
105 27
    public function getBuild(): Build
106
    {
107 27
        return $this->build;
108
    }
109
110
    /**
111
     * @param Version|string $version
112
     * @return bool
113
     */
114 6
    public function isEqualTo($version): bool
115
    {
116 6
        return $this->compareTo($version) === 0;
117
    }
118
119
    /**
120
     * @param Version|string $version
121
     * @return bool
122
     */
123 1
    public function isNotEqualTo($version): bool
124
    {
125 1
        return !$this->isEqualTo($version);
126
    }
127
128
    /**
129
     * @param Version|string $version
130
     * @return bool
131
     */
132 3
    public function isGreaterThan($version): bool
133
    {
134 3
        return $this->compareTo($version) > 0;
135
    }
136
137
    /**
138
     * @param Version|string $version
139
     * @return bool
140
     */
141 6
    public function isGreaterOrEqualTo($version): bool
142
    {
143 6
        return $this->compareTo($version) >= 0;
144
    }
145
146
    /**
147
     * @param Version|string $version
148
     * @return bool
149
     */
150 3
    public function isLessThan($version): bool
151
    {
152 3
        return $this->compareTo($version) < 0;
153
    }
154
155
    /**
156
     * @param Version|string $version
157
     * @return bool
158
     */
159 2
    public function isLessOrEqualTo($version): bool
160
    {
161 2
        return $this->compareTo($version) <= 0;
162
    }
163
164
    /**
165
     * @param Version|string $version
166
     * @return int (1 if $this > $version, -1 if $this < $version, 0 if equal)
167
     */
168 25
    public function compareTo($version): int
169
    {
170 25
        if (is_string($version)) {
171 7
            $version = static::fromString($version);
172
        }
173
174 25
        return $this->getComparator()->compare($this, $version);
175
    }
176
177 2
    public function isMajorRelease(): bool
178
    {
179 2
        return $this->major > 0 && $this->minor === 0 && $this->patch === 0;
180
    }
181
182 1
    public function isMinorRelease(): bool
183
    {
184 1
        return $this->minor > 0 && $this->patch === 0;
185
    }
186
187 1
    public function isPatchRelease(): bool
188
    {
189 1
        return $this->patch > 0;
190
    }
191
192 38
    public function isPreRelease(): bool
193
    {
194 38
        return !$this->preRelease->isEmpty();
195
    }
196
197 15
    public function hasBuild(): bool
198
    {
199 15
        return !$this->build->isEmpty();
200
    }
201
202 1
    public function incrementMajor(): Version
203
    {
204 1
        return static::from($this->major + 1, 0, 0, new NoPreRelease(), new NoBuild());
205
    }
206
207 2
    public function incrementMinor(): Version
208
    {
209 2
        return static::from($this->major, $this->minor + 1, 0, new NoPreRelease(), new NoBuild());
210
    }
211
212 1
    public function incrementPatch(): Version
213
    {
214 1
        return static::from($this->major, $this->minor, $this->patch + 1, new NoPreRelease(), new NoBuild());
215
    }
216
217
    /**
218
     * @param PreRelease|string|null $preRelease
219
     * @return Version
220
     */
221 2
    public function withPreRelease($preRelease): Version
222
    {
223 2
        if (is_string($preRelease)) {
224 2
            $preRelease = PreRelease::fromIdentifiersString($preRelease);
225
        }
226
227 2
        return static::from($this->major, $this->minor, $this->patch, $preRelease, new NoBuild());
228
    }
229
230
    /**
231
     * @param Build|string|null $build
232
     * @return Version
233
     */
234 1
    public function withBuild($build): Version
235
    {
236 1
        if (is_string($build)) {
237 1
            $build = Build::fromIdentifiersString($build);
238
        }
239
240 1
        return static::from($this->major, $this->minor, $this->patch, $this->preRelease, $build);
241
    }
242
243 4
    public function matches(Constraint $constraint): bool
244
    {
245 4
        return $constraint->assert($this);
246
    }
247
248 14
    public function toString(): string
249
    {
250
        return
251 14
            $this->major
252 14
            . '.' . $this->minor
253 14
            . '.' . $this->patch
254 14
            . ($this->isPreRelease() ? '-' . $this->preRelease : '')
255 14
            . ($this->hasBuild() ? '+' . $this->build : '')
256
        ;
257
    }
258
259 10
    public function __toString(): string
260
    {
261 10
        return $this->toString();
262
    }
263
264 4
    public function jsonSerialize(): string
265
    {
266 4
        return $this->toString();
267
    }
268
269 4
    public function toArray(): array
270
    {
271
        return [
272 4
            'major' => $this->major,
273 4
            'minor' => $this->minor,
274 4
            'patch' => $this->patch,
275 4
            'preRelease' => $this->preRelease->getIdentifiers(),
276 4
            'build' => $this->build->getIdentifiers(),
277
        ];
278
    }
279
280 1
    public static function setComparator(?Comparator $comparator): void
281
    {
282 1
        static::$comparator = $comparator;
283 1
    }
284
285 25
    protected function getComparator(): Comparator
286
    {
287 25
        if (null === static::$comparator) {
288 1
            static::$comparator = new SemverComparator();
289
        }
290
291 25
        return static::$comparator;
292
    }
293
}
294