Completed
Push — master ( a68676...5119d9 )
by Nikola
01:13
created

Version   B

Complexity

Total Complexity 48

Size/Duplication

Total Lines 264
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 97.98%

Importance

Changes 0
Metric Value
wmc 48
lcom 1
cbo 7
dl 0
loc 264
ccs 97
cts 99
cp 0.9798
rs 8.5599
c 0
b 0
f 0

32 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 12 1
A from() 0 4 1
A getMajor() 0 4 1
A getMinor() 0 4 1
A getPatch() 0 4 1
A getPreRelease() 0 4 1
A getBuild() 0 4 1
A isEqualTo() 0 4 1
A isNotEqualTo() 0 4 1
A isGreaterThan() 0 4 1
A isGreaterOrEqualTo() 0 4 1
A isLessThan() 0 4 1
A isLessOrEqualTo() 0 4 1
A compareTo() 0 8 2
A isMajorRelease() 0 4 3
A isMinorRelease() 0 4 2
A isPatchRelease() 0 4 1
A isPreRelease() 0 4 1
A hasBuild() 0 4 1
A incrementMajor() 0 4 1
A incrementMinor() 0 4 1
A incrementPatch() 0 4 1
A withPreRelease() 0 8 2
A withBuild() 0 8 2
A matches() 0 4 1
A toString() 0 10 3
A __toString() 0 4 1
A jsonSerialize() 0 4 1
A toArray() 0 10 3
A setComparator() 0 4 1
A getComparator() 0 8 2
B fromString() 0 23 6

How to fix   Complexity   

Complex Class

Complex classes like Version often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Version, and based on these observations, apply Extract Interface, too.

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