Completed
Pull Request — master (#13)
by Nikola
01:52
created

Version::incrementMinor()   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 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Version;
6
7
use JsonSerializable;
8
use Version\Metadata\PreRelease;
9
use Version\Metadata\Build;
10
use Version\Exception\InvalidVersionElementException;
11
use Version\Exception\InvalidVersionStringException;
12
use Version\Comparator\ComparatorInterface;
13
use Version\Comparator\SemverComparator;
14
use Version\Constraint\ConstraintInterface;
15
use Version\Constraint\Constraint;
16
17
/**
18
 * @author Nikola Posa <[email protected]>
19
 */
20
class Version implements JsonSerializable
21
{
22
    /**
23
     * @var int
24
     */
25
    protected $major;
26
27
    /**
28
     * @var int
29
     */
30
    protected $minor;
31
32
    /**
33
     * @var int
34
     */
35
    protected $patch;
36
37
    /**
38
     * @var PreRelease
39
     */
40
    protected $preRelease;
41
42
    /**
43
     * @var Build
44
     */
45
    protected $build;
46
47
    /**
48
     * @var ComparatorInterface
49
     */
50
    protected static $comparator;
51
52 74
    protected function __construct(int $major, int $minor, int $patch, PreRelease $preRelease, Build $build)
53
    {
54 74
        $this->major = $major;
55 74
        $this->minor = $minor;
56 74
        $this->patch = $patch;
57 74
        $this->preRelease = $preRelease;
58 74
        $this->build = $build;
59 74
    }
60
61 77
    public static function fromParts(int $major, int $minor, int $patch, PreRelease $preRelease, Build $build) : Version
62
    {
63 77
        self::validatePart('major', $major);
64 76
        self::validatePart('minor', $minor);
65 75
        self::validatePart('patch', $patch);
66
67 74
        return new self($major, $minor, $patch, $preRelease, $build);
68
    }
69
70 10
    public static function fromMajor(int $major) : Version
71
    {
72 10
        return self::fromParts($major, 0, 0, PreRelease::createEmpty(), Build::createEmpty());
73
    }
74
75 2
    public static function fromMinor(int $major, int $minor) : Version
76
    {
77 2
        return self::fromParts($major, $minor, 0, PreRelease::createEmpty(), Build::createEmpty());
78
    }
79
80 2
    public static function fromPatch(int $major, int $minor, int $patch) : Version
81
    {
82 2
        return self::fromParts($major, $minor, $patch, PreRelease::createEmpty(), Build::createEmpty());
83
    }
84
85 1
    public static function fromPreRelease(int $major, int $minor, int $patch, PreRelease $preRelease) : Version
86
    {
87 1
        return self::fromParts($major, $minor, $patch, $preRelease, Build::createEmpty());
88
    }
89
90 1
    public static function fromBuild(int $major, int $minor, int $patch, Build $build) : Version
91
    {
92 1
        return self::fromParts($major, $minor, $patch, PreRelease::createEmpty(), $build);
93
    }
94
95
    /**
96
     * @param string $versionString
97
     * @return Version
98
     * @throws InvalidVersionStringException
99
     */
100 71
    public static function fromString(string $versionString) : Version
101
    {
102 71
        $parts = [];
103
104 71
        if (!preg_match(
105
            '#^'
106
            . '(?P<core>(?:[0-9]|[1-9][0-9]+)(?:\.(?:[0-9]|[1-9][0-9]+)){2})'
107
            . '(?:\-(?P<preRelease>[0-9A-Za-z\-\.]+))?'
108
            . '(?:\+(?P<build>[0-9A-Za-z\-\.]+))?'
109 71
            . '$#',
110 71
            (string) $versionString,
111 71
            $parts
112
        )) {
113 4
            throw InvalidVersionStringException::forVersionString($versionString);
114
        }
115
116 67
        list($major, $minor, $patch) = explode('.', $parts['core']);
117 67
        $major = (int) $major;
118 67
        $minor = (int) $minor;
119 67
        $patch = (int) $patch;
120
121 67
        $preRelease = (!empty($parts['preRelease'])) ? PreRelease::create($parts['preRelease']) : PreRelease::createEmpty();
122
123 66
        $build = (!empty($parts['build'])) ? Build::create($parts['build']) : Build::createEmpty();
124
125 66
        return self::fromParts($major, $minor, $patch, $preRelease, $build);
126
    }
127
128 77
    protected static function validatePart(string $part, int $value)
129
    {
130 77
        if ($value < 0) {
131 3
            throw InvalidVersionElementException::forElement($part);
132
        }
133 76
    }
134
135 54
    public function getMajor() : int
136
    {
137 54
        return $this->major;
138
    }
139
140 50
    public function getMinor() : int
141
    {
142 50
        return $this->minor;
143
    }
144
145 46
    public function getPatch() : int
146
    {
147 46
        return $this->patch;
148
    }
149
150 29
    public function getPreRelease() : PreRelease
151
    {
152 29
        return $this->preRelease;
153
    }
154
155 7
    public function getBuild() : Build
156
    {
157 7
        return $this->build;
158
    }
159
160 48
    public function isPreRelease() : bool
161
    {
162 48
        return !$this->preRelease->isEmpty();
163
    }
164
165 28
    public function isBuild() : bool
166
    {
167 28
        return !$this->build->isEmpty();
168
    }
169
170
    /**
171
     * @param self|string $version
172
     * @return int (1 if $this > $version, -1 if $this < $version, 0 if equal)
173
     */
174 21
    public function compareTo($version) : int
175
    {
176 21
        if (!$version instanceof self) {
177 7
            $version = self::fromString((string) $version);
178
        }
179
180 21
        return self::getComparator()->compare($this, $version);
181
    }
182
183
    /**
184
     * @param self|string $version
185
     * @return bool
186
     */
187 5
    public function isEqualTo($version) : bool
188
    {
189 5
        return $this->compareTo($version) === 0;
190
    }
191
192
    /**
193
     * @param self|string $version
194
     * @return bool
195
     */
196 1
    public function isNotEqualTo($version) : bool
197
    {
198 1
        return !$this->isEqualTo($version);
199
    }
200
201
    /**
202
     * @param self|string $version
203
     * @return bool
204
     */
205 3
    public function isGreaterThan($version) : bool
206
    {
207 3
        return $this->compareTo($version) > 0;
208
    }
209
210
    /**
211
     * @param self|string $version
212
     * @return bool
213
     */
214 4
    public function isGreaterOrEqualTo($version) : bool
215
    {
216 4
        return $this->compareTo($version) >= 0;
217
    }
218
219
    /**
220
     * @param self|string $version
221
     * @return bool
222
     */
223 3
    public function isLessThan($version) : bool
224
    {
225 3
        return $this->compareTo($version) < 0;
226
    }
227
228
    /**
229
     * @param self|string $version
230
     * @return bool
231
     */
232 3
    public function isLessOrEqualTo($version) : bool
233
    {
234 3
        return $this->compareTo($version) <= 0;
235
    }
236
237
    /**
238
     * @param ConstraintInterface|string $constraint
239
     * @return bool
240
     */
241 3
    public function matches($constraint) : bool
242
    {
243 3
        if (! $constraint instanceof ConstraintInterface) {
244 1
            $constraint = Constraint::fromString($constraint);
245
        }
246
247 3
        return $constraint->assert($this);
248
    }
249
250 1
    public function incrementMajor() : Version
251
    {
252 1
        return self::fromParts($this->major + 1, 0, 0, PreRelease::createEmpty(), Build::createEmpty());
253
    }
254
255 2
    public function incrementMinor() : Version
256
    {
257 2
        return self::fromParts($this->major, $this->minor + 1, 0, PreRelease::createEmpty(), Build::createEmpty());
258
    }
259
260 1
    public function incrementPatch() : Version
261
    {
262 1
        return self::fromParts($this->major, $this->minor, $this->patch + 1, PreRelease::createEmpty(), Build::createEmpty());
263
    }
264
265 2
    public function withPreRelease($preRelease) : Version
266
    {
267 2
        return self::fromParts($this->major, $this->minor, $this->patch, PreRelease::create($preRelease), Build::createEmpty());
268
    }
269
270 1
    public function withBuild($build) : Version
271
    {
272 1
        return self::fromParts($this->major, $this->minor, $this->patch, $this->preRelease, Build::create($build));
273
    }
274
275 14
    public function getVersionString() : string
276
    {
277
        return
278 14
            $this->major
279 14
            . '.' . $this->minor
280 14
            . '.' . $this->patch
281 14
            . ($this->isPreRelease() ? '-' . (string) $this->preRelease : '')
282 14
            . ($this->isBuild() ? '+' . (string) $this->build : '')
283
            ;
284
    }
285
286 10
    public function __toString() : string
287
    {
288 10
        return $this->getVersionString();
289
    }
290
291 4
    public function jsonSerialize() : string
292
    {
293 4
        return $this->getVersionString();
294
    }
295
296 4
    public function toArray() : array
297
    {
298
        return [
299 4
            'major' => $this->major,
300 4
            'minor' => $this->minor,
301 4
            'patch' => $this->patch,
302 4
            'preRelease' => $this->preRelease->toArray(),
303 4
            'build' => $this->build->toArray(),
304
        ];
305
    }
306
307 21
    public static function getComparator() : ComparatorInterface
308
    {
309 21
        if (null === self::$comparator) {
310 1
            self::setComparator(new SemverComparator());
311
        }
312
313 21
        return self::$comparator;
314
    }
315
316 1
    public static function setComparator(ComparatorInterface $comparator) : void
317
    {
318 1
        self::$comparator = $comparator;
319 1
    }
320
}
321