1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of questocat/version-comparator package. |
5
|
|
|
* |
6
|
|
|
* (c) questocat <[email protected]> |
7
|
|
|
* |
8
|
|
|
* This source file is subject to the MIT license that is bundled |
9
|
|
|
* with this source code in the file LICENSE. |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace Questocat\VersionComparator; |
13
|
|
|
|
14
|
|
|
/** |
15
|
|
|
* Compare the version number strings according to the "Semantic Versioning 2.0.0". |
16
|
|
|
* |
17
|
|
|
* @see http://semver.org Semantic Versioning |
18
|
|
|
*/ |
19
|
|
|
class VersionComparator |
20
|
|
|
{ |
21
|
|
|
const COMPARE_LESS_THAN = -1; |
22
|
|
|
|
23
|
|
|
const COMPARE_EQUAL_TO = 0; |
24
|
|
|
|
25
|
|
|
const COMPARE_GREATER_THAN = 1; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* Compares version number strings. |
29
|
|
|
* |
30
|
|
|
* returns -1 if the first version is lower than the second, 0 if they are equal, and 1 if the second is lower |
31
|
|
|
* |
32
|
|
|
* @param Version $version1 |
33
|
|
|
* @param Version $version2 |
34
|
|
|
* |
35
|
|
|
* @return int |
36
|
|
|
*/ |
37
|
8 |
|
public function versionCompare(Version $version1, Version $version2) |
38
|
|
|
{ |
39
|
8 |
|
$compare = $this->compareStandardVersion($version1, $version2); |
40
|
|
|
|
41
|
8 |
|
if (0 == $compare) { |
42
|
6 |
|
$compare = $this->comparePreReleaseVersion($version1, $version2); |
43
|
6 |
|
} |
44
|
|
|
|
45
|
8 |
|
return $compare; |
46
|
|
|
} |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* Returns a Boolean value. |
50
|
|
|
* |
51
|
|
|
* Can use the comparison operator |
52
|
|
|
* <、 lt、<=、 le、>、 gt、>=、 ge、==、 =、eq、 !=、<> and ne |
53
|
|
|
* |
54
|
|
|
* @param int $compare |
55
|
|
|
* @param string $operator |
56
|
|
|
* |
57
|
|
|
* @return bool|null |
58
|
|
|
*/ |
59
|
3 |
|
public function returnBool($compare, $operator) |
60
|
|
|
{ |
61
|
3 |
|
$compareLen = strlen($operator); |
62
|
|
|
|
63
|
3 |
|
if (!strncmp($operator, '<', $compareLen) || !strncmp($operator, 'lt', $compareLen)) { |
64
|
3 |
|
return self::COMPARE_LESS_THAN == $compare; |
65
|
|
|
} |
66
|
|
|
|
67
|
3 |
View Code Duplication |
if (!strncmp($operator, '<=', $compareLen) || !strncmp($operator, 'le', $compareLen)) { |
|
|
|
|
68
|
1 |
|
return self::COMPARE_GREATER_THAN != $compare; |
69
|
|
|
} |
70
|
|
|
|
71
|
3 |
|
if (!strncmp($operator, '>', $compareLen) || !strncmp($operator, 'gt', $compareLen)) { |
72
|
3 |
|
return self::COMPARE_GREATER_THAN == $compare; |
73
|
|
|
} |
74
|
|
|
|
75
|
2 |
View Code Duplication |
if (!strncmp($operator, '>=', $compareLen) || !strncmp($operator, 'ge', $compareLen)) { |
|
|
|
|
76
|
1 |
|
return self::COMPARE_LESS_THAN != $compare; |
77
|
|
|
} |
78
|
|
|
|
79
|
2 |
View Code Duplication |
if (!strncmp($operator, '==', $compareLen) || !strncmp($operator, '=', $compareLen) || !strncmp($operator, 'eq', $compareLen)) { |
|
|
|
|
80
|
2 |
|
return self::COMPARE_EQUAL_TO == $compare; |
81
|
|
|
} |
82
|
|
|
|
83
|
1 |
View Code Duplication |
if (!strncmp($operator, '!=', $compareLen) || !strncmp($operator, '<>', $compareLen) || !strncmp($operator, 'ne', $compareLen)) { |
|
|
|
|
84
|
1 |
|
return self::COMPARE_EQUAL_TO != $compare; |
85
|
|
|
} |
86
|
|
|
|
87
|
1 |
|
return null; |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
/** |
91
|
|
|
* Compares the standard version. |
92
|
|
|
* |
93
|
|
|
* 1.0.0 < 2.0.0 < 2.1.0 < 2.1.1 |
94
|
|
|
* |
95
|
|
|
* @param Version $version1 |
96
|
|
|
* @param Version $version2 |
97
|
|
|
* |
98
|
|
|
* @return int |
99
|
|
|
*/ |
100
|
8 |
|
protected function compareStandardVersion(Version $version1, Version $version2) |
101
|
|
|
{ |
102
|
8 |
|
$version1Str = strval($version1->getMajor().$version1->getMinor().$version1->getPatch()); |
103
|
8 |
|
$version2Str = strval($version2->getMajor().$version2->getMinor().$version2->getPatch()); |
104
|
|
|
|
105
|
8 |
|
return version_compare($version1Str, $version2Str); |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
/** |
109
|
|
|
* Compares the pre-release version. |
110
|
|
|
* |
111
|
|
|
* 1.0.0-alpha < 1.0.0 |
112
|
|
|
* |
113
|
|
|
* @param Version $version1 |
114
|
|
|
* @param Version $version2 |
115
|
|
|
* |
116
|
|
|
* @return int |
117
|
|
|
*/ |
118
|
6 |
|
protected function comparePreReleaseVersion(Version $version1, Version $version2) |
119
|
|
|
{ |
120
|
6 |
|
$preRelease1 = $version1->getPreRelease(); |
121
|
6 |
|
$preRelease2 = $version2->getPreRelease(); |
122
|
|
|
|
123
|
6 |
|
if (!empty($preRelease1) || !empty($preRelease2)) { |
124
|
6 |
|
if (!empty($preRelease1) && empty($preRelease2)) { |
125
|
1 |
|
return self::COMPARE_LESS_THAN; |
126
|
|
|
} |
127
|
|
|
|
128
|
6 |
|
if (empty($preRelease1) && !empty($preRelease2)) { |
129
|
3 |
|
return self::COMPARE_GREATER_THAN; |
130
|
|
|
} |
131
|
|
|
|
132
|
5 |
|
$left = $preRelease1; |
133
|
5 |
|
$right = $preRelease2; |
134
|
5 |
|
$lt = self::COMPARE_LESS_THAN; |
135
|
5 |
|
$gt = self::COMPARE_GREATER_THAN; |
136
|
|
|
|
137
|
5 |
|
if (count($preRelease1) < count($preRelease2)) { |
138
|
1 |
|
$left = $preRelease2; |
139
|
1 |
|
$right = $preRelease1; |
140
|
1 |
|
$lt = self::COMPARE_GREATER_THAN; |
141
|
1 |
|
$gt = self::COMPARE_LESS_THAN; |
142
|
1 |
|
} |
143
|
|
|
|
144
|
5 |
|
foreach ($left as $index => $leftItem) { |
145
|
5 |
|
if (!isset($right[$index])) { |
146
|
1 |
|
return $gt; |
147
|
|
|
} |
148
|
|
|
|
149
|
5 |
|
$rightItem = $right[$index]; |
150
|
|
|
|
151
|
5 |
|
if ($leftItem == $rightItem) { |
152
|
5 |
|
continue; |
153
|
|
|
} |
154
|
|
|
|
155
|
4 |
|
$leftIsNumeric = is_numeric($leftItem); |
156
|
4 |
|
$rightIsNumeric = is_numeric($rightItem); |
157
|
|
|
|
158
|
4 |
|
if ($leftIsNumeric && $rightIsNumeric) { |
159
|
3 |
|
return $leftItem < $rightItem ? $lt : $gt; |
160
|
|
|
} |
161
|
|
|
|
162
|
1 |
|
if ($leftIsNumeric && !$rightIsNumeric) { |
163
|
1 |
|
return $lt; |
164
|
|
|
} |
165
|
|
|
|
166
|
1 |
|
if (!$leftIsNumeric && $rightIsNumeric) { |
167
|
1 |
|
return $gt; |
168
|
|
|
} |
169
|
|
|
|
170
|
1 |
|
$compare = strcmp($leftItem, $rightItem); |
171
|
|
|
|
172
|
1 |
|
if ($compare) { |
173
|
1 |
|
return $compare > 0 ? $gt : $lt; |
174
|
|
|
} |
175
|
3 |
|
} |
176
|
3 |
|
} |
177
|
|
|
|
178
|
3 |
|
return self::COMPARE_EQUAL_TO; |
179
|
|
|
} |
180
|
|
|
} |
181
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.