Completed
Pull Request — master (#9)
by Nikola
02:21
created

Version::withBuild()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
3
/**
4
 * This file is part of the Version package.
5
 *
6
 * Copyright (c) Nikola Posa <[email protected]>
7
 *
8
 * For full copyright and license information, please refer to the LICENSE file,
9
 * located at the package root folder.
10
 */
11
12
namespace Version;
13
14
use JsonSerializable;
15
use Version\Metadata\PreRelease;
16
use Version\Metadata\Build;
17
use Version\Exception\InvalidVersionElementException;
18
use Version\Exception\InvalidVersionStringException;
19
use Version\Comparator\ComparatorInterface;
20
use Version\Comparator\SemverComparator;
21
use Version\Constraint\ConstraintInterface;
22
use Version\Constraint\Constraint;
23
24
/**
25
 * @author Nikola Posa <[email protected]>
26
 */
27
final class Version implements JsonSerializable
28
{
29
    /**
30
     * @var int
31
     */
32
    private $major;
33
34
    /**
35
     * @var int
36
     */
37
    private $minor;
38
39
    /**
40
     * @var int
41
     */
42
    private $patch;
43
44
    /**
45
     * @var PreRelease
46
     */
47
    private $preRelease;
48
49
    /**
50
     * @var Build
51
     */
52
    private $build;
53
54
    /**
55
     * @var ComparatorInterface
56
     */
57
    private static $comparator;
58
59 77
    private function __construct($major, $minor, $patch, PreRelease $preRelease, Build $build)
60
    {
61 77
        $this->major = $major;
62 77
        $this->minor = $minor;
63 77
        $this->patch = $patch;
64 77
        $this->preRelease = $preRelease;
65 77
        $this->build = $build;
66 77
    }
67
68
    /**
69
     * @param int $major
70
     * @param int $minor
71
     * @param int $patch
72
     * @param PreRelease|array|string $preRelease
73
     * @param Build|array|string $build
74
     * @return self
75
     */
76 81
    public static function fromAllElements($major, $minor, $patch, $preRelease, $build)
77
    {
78 81
        self::validateVersionElement('major', $major);
79
80 80
        self::validateVersionElement('minor', $minor);
81
82 79
        self::validateVersionElement('patch', $patch);
83
84 78
        if (!$preRelease instanceof PreRelease) {
85 25
            $preRelease = PreRelease::create($preRelease);
86 24
        }
87
88 77
        if (!$build instanceof Build) {
89 12
            $build = Build::create($build);
90 12
        }
91
92 77
        return new self($major, $minor, $patch, $preRelease, $build);
93
    }
94
95 81
    private static function validateVersionElement($element, $value)
96
    {
97 81
        if (!is_int($value) || $value < 0) {
98 3
            throw InvalidVersionElementException::forElement($element);
99
        }
100 80
    }
101
102
    /**
103
     * @param int $major
104
     * @return self
105
     */
106 12
    public static function fromMajor($major)
107
    {
108 12
        return self::fromAllElements($major, 0, 0, PreRelease::createEmpty(), Build::createEmpty());
109
    }
110
111
    /**
112
     * @param int $major
113
     * @param int $minor
114
     * @return self
115
     */
116 2
    public static function fromMinor($major, $minor)
117
    {
118 2
        return self::fromAllElements($major, $minor, 0, PreRelease::createEmpty(), Build::createEmpty());
119
    }
120
121
    /**
122
     * @param int $major
123
     * @param int $minor
124
     * @param int $patch
125
     * @return self
126
     */
127 2
    public static function fromPatch($major, $minor, $patch)
128
    {
129 2
        return self::fromAllElements($major, $minor, $patch, PreRelease::createEmpty(), Build::createEmpty());
130
    }
131
132
    /**
133
     * @param int $major
134
     * @param int $minor
135
     * @param int $patch
136
     * @param @param PreRelease|array|string $preRelease
137
     * @return self
138
     */
139 1
    public static function fromPreRelease($major, $minor, $patch, $preRelease)
140
    {
141 1
        return self::fromAllElements($major, $minor, $patch, $preRelease, Build::createEmpty());
142
    }
143
144
    /**
145
     * @param int $major
146
     * @param int $minor
147
     * @param int $patch
148
     * @param Build|array|string $build
149
     * @return self
150
     */
151 1
    public static function fromBuild($major, $minor, $patch, $build)
152
    {
153 1
        return self::fromAllElements($major, $minor, $patch, PreRelease::createEmpty(), $build);
154
    }
155
156
    /**
157
     * @param string $versionString
158
     * @return self
159
     * @throws InvalidVersionStringException
160
     */
161 74
    public static function fromString($versionString)
162
    {
163 74
        $parts = [];
164
165 74
        if (!preg_match(
166
            '#^'
167
            . '(?P<core>(?:[0-9]|[1-9][0-9]+)(?:\.(?:[0-9]|[1-9][0-9]+)){2})'
168 74
            . '(?:\-(?P<preRelease>[0-9A-Za-z\-\.]+))?'
169 74
            . '(?:\+(?P<build>[0-9A-Za-z\-\.]+))?'
170 74
            . '$#',
171 74
            (string) $versionString,
172
            $parts
173 74
        )) {
174 4
            throw new InvalidVersionStringException("Version string is not valid and cannot be parsed");
175
        }
176
177 70
        list($major, $minor, $patch) = explode('.', $parts['core']);
178 70
        $major = (int) $major;
179 70
        $minor = (int) $minor;
180 70
        $patch = (int) $patch;
181
182 70
        $preRelease = (!empty($parts['preRelease'])) ? $parts['preRelease'] : PreRelease::createEmpty();
183
184 70
        $build = (!empty($parts['build'])) ? $parts['build'] : Build::createEmpty();
185
186 70
        return self::fromAllElements($major, $minor, $patch, $preRelease, $build);
187
    }
188
189
    /**
190
     * @return int
191
     */
192 55
    public function getMajor()
193
    {
194 55
        return $this->major;
195
    }
196
197
    /**
198
     * @return int
199
     */
200 51
    public function getMinor()
201
    {
202 51
        return $this->minor;
203
    }
204
205
    /**
206
     * @return int
207
     */
208 45
    public function getPatch()
209
    {
210 45
        return $this->patch;
211
    }
212
213
    /**
214
     * @return PreRelease
215
     */
216 28
    public function getPreRelease()
217
    {
218 28
        return $this->preRelease;
219
    }
220
221
    /**
222
     * @return Build
223
     */
224 7
    public function getBuild()
225
    {
226 7
        return $this->build;
227
    }
228
229
    /**
230
     * @return bool
231
     */
232 49
    public function isPreRelease()
233
    {
234 49
        return !$this->preRelease->isEmpty();
235
    }
236
237
    /**
238
     * @return bool
239
     */
240 30
    public function isBuild()
241
    {
242 30
        return !$this->build->isEmpty();
243
    }
244
245
    /**
246
     * @param self|string $version
247
     * @return int (1 if $this > $version, -1 if $this < $version, 0 if equal)
248
     */
249 22
    public function compareTo($version)
250
    {
251 22
        if (!$version instanceof self) {
252 7
            $version = self::fromString((string) $version);
253 7
        }
254
255 22
        return self::getComparator()->compare($this, $version);
256
    }
257
258
    /**
259
     * @param ComparatorInterface $comparator
260
     * @return void
261
     */
262 1
    public static function setComparator(ComparatorInterface $comparator)
263
    {
264 1
        self::$comparator = $comparator;
265 1
    }
266
267
    /**
268
     * @return ComparatorInterface
269
     */
270 22
    public static function getComparator()
271
    {
272 22
        if (!isset(self::$comparator)) {
273 1
            self::setComparator(new SemverComparator());
274 1
        }
275
276 22
        return self::$comparator;
277
    }
278
279
    /**
280
     * @param self|string $version
281
     * @return bool
282
     */
283 5
    public function isEqualTo($version)
284
    {
285 5
        return $this->compareTo($version) == 0;
286
    }
287
288
    /**
289
     * @param self|string $version
290
     * @return bool
291
     */
292 1
    public function isNotEqualTo($version)
293
    {
294 1
        return !$this->isEqualTo($version);
295
    }
296
297
    /**
298
     * @param self|string $version
299
     * @return bool
300
     */
301 3
    public function isGreaterThan($version)
302
    {
303 3
        return $this->compareTo($version) > 0;
304
    }
305
306
    /**
307
     * @param self|string $version
308
     * @return bool
309
     */
310 3
    public function isGreaterOrEqualTo($version)
311
    {
312 3
        return $this->compareTo($version) >= 0;
313
    }
314
315
    /**
316
     * @param self|string $version
317
     * @return bool
318
     */
319 3
    public function isLessThan($version)
320
    {
321 3
        return $this->compareTo($version) < 0;
322
    }
323
324
    /**
325
     * @param self|string $version
326
     * @return bool
327
     */
328 3
    public function isLessOrEqualTo($version)
329
    {
330 3
        return $this->compareTo($version) <= 0;
331
    }
332
333
    /**
334
     * @param ConstraintInterface|string $constraint
335
     * @return bool
336
     */
337 2
    public function matches($constraint)
338
    {
339 2
        if (!$constraint instanceof ConstraintInterface) {
340 1
            $constraint = Constraint::fromString($constraint);
341 1
        }
342
343 2
        return $constraint->assert($this);
344
    }
345
346
    /**
347
     * @return self
348
     */
349 1
    public function withMajorIncremented()
350
    {
351 1
        return self::fromAllElements($this->major + 1, 0, 0, PreRelease::createEmpty(), Build::createEmpty());
352
    }
353
354
    /**
355
     * @return self
356
     */
357 2
    public function withMinorIncremented()
358
    {
359 2
        return self::fromAllElements($this->major, $this->minor + 1, 0, PreRelease::createEmpty(), Build::createEmpty());
360
    }
361
362
    /**
363
     * @return self
364
     */
365 1
    public function withPatchIncremented()
366
    {
367 1
        return self::fromAllElements($this->major, $this->minor, $this->patch + 1, PreRelease::createEmpty(), Build::createEmpty());
368
    }
369
370
    /**
371
     * @param PreRelease|array|string $preRelease
372
     * @return self
373
     */
374 2
    public function withPreRelease($preRelease)
375
    {
376 2
        return self::fromAllElements($this->major, $this->minor, $this->patch, $preRelease, Build::createEmpty());
377
    }
378
379
    /**
380
     * @param Build|array|string $build
381
     * @return self
382
     */
383 1
    public function withBuild($build)
384
    {
385 1
        return self::fromAllElements($this->major, $this->minor, $this->patch, $this->preRelease, $build);
386
    }
387
388
    /**
389
     * @return string
390
     */
391 16
    public function getVersionString()
392
    {
393
        return
394 16
            $this->major
395 16
            . '.' . $this->minor
396 16
            . '.' . $this->patch
397 16
            . ($this->isPreRelease() ? '-' . (string) $this->preRelease : '')
398 16
            . ($this->isBuild() ? '+' . (string) $this->build : '')
399 16
            ;
400
    }
401
402
    /**
403
     * @return string
404
     */
405 12
    public function __toString()
406
    {
407 12
        return $this->getVersionString();
408
    }
409
410
    /**
411
     * @return string
412
     */
413 4
    public function jsonSerialize()
414
    {
415 4
        return $this->getVersionString();
416
    }
417
418
    /**
419
     * @return array
420
     */
421 4
    public function toArray()
422
    {
423
        return [
424 4
            'major' => $this->major,
425 4
            'minor' => $this->minor,
426 4
            'patch' => $this->patch,
427 4
            'preRelease' => $this->preRelease->toArray(),
428 4
            'build' => $this->build->toArray(),
429 4
        ];
430
    }
431
}
432