comparison vendor/composer/semver/src/Constraint/Constraint.php @ 0:1e000243b222

vanilla 1.3.3 distro, I hope
author Charlie Root
date Thu, 04 Jan 2018 15:50:29 -0500
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:1e000243b222
1 <?php
2
3 /*
4 * This file is part of composer/semver.
5 *
6 * (c) Composer <https://github.com/composer>
7 *
8 * For the full copyright and license information, please view
9 * the LICENSE file that was distributed with this source code.
10 */
11
12 namespace Composer\Semver\Constraint;
13
14 /**
15 * Defines a constraint.
16 */
17 class Constraint implements ConstraintInterface
18 {
19 /* operator integer values */
20 const OP_EQ = 0;
21 const OP_LT = 1;
22 const OP_LE = 2;
23 const OP_GT = 3;
24 const OP_GE = 4;
25 const OP_NE = 5;
26
27 /**
28 * Operator to integer translation table.
29 *
30 * @var array
31 */
32 private static $transOpStr = array(
33 '=' => self::OP_EQ,
34 '==' => self::OP_EQ,
35 '<' => self::OP_LT,
36 '<=' => self::OP_LE,
37 '>' => self::OP_GT,
38 '>=' => self::OP_GE,
39 '<>' => self::OP_NE,
40 '!=' => self::OP_NE,
41 );
42
43 /**
44 * Integer to operator translation table.
45 *
46 * @var array
47 */
48 private static $transOpInt = array(
49 self::OP_EQ => '==',
50 self::OP_LT => '<',
51 self::OP_LE => '<=',
52 self::OP_GT => '>',
53 self::OP_GE => '>=',
54 self::OP_NE => '!=',
55 );
56
57 /** @var string */
58 protected $operator;
59
60 /** @var string */
61 protected $version;
62
63 /** @var string */
64 protected $prettyString;
65
66 /**
67 * @param ConstraintInterface $provider
68 *
69 * @return bool
70 */
71 public function matches(ConstraintInterface $provider)
72 {
73 if ($provider instanceof $this) {
74 return $this->matchSpecific($provider);
75 }
76
77 // turn matching around to find a match
78 return $provider->matches($this);
79 }
80
81 /**
82 * @param string $prettyString
83 */
84 public function setPrettyString($prettyString)
85 {
86 $this->prettyString = $prettyString;
87 }
88
89 /**
90 * @return string
91 */
92 public function getPrettyString()
93 {
94 if ($this->prettyString) {
95 return $this->prettyString;
96 }
97
98 return $this->__toString();
99 }
100
101 /**
102 * Get all supported comparison operators.
103 *
104 * @return array
105 */
106 public static function getSupportedOperators()
107 {
108 return array_keys(self::$transOpStr);
109 }
110
111 /**
112 * Sets operator and version to compare with.
113 *
114 * @param string $operator
115 * @param string $version
116 *
117 * @throws \InvalidArgumentException if invalid operator is given.
118 */
119 public function __construct($operator, $version)
120 {
121 if (!isset(self::$transOpStr[$operator])) {
122 throw new \InvalidArgumentException(sprintf(
123 'Invalid operator "%s" given, expected one of: %s',
124 $operator,
125 implode(', ', self::getSupportedOperators())
126 ));
127 }
128
129 $this->operator = self::$transOpStr[$operator];
130 $this->version = $version;
131 }
132
133 /**
134 * @param string $a
135 * @param string $b
136 * @param string $operator
137 * @param bool $compareBranches
138 *
139 * @throws \InvalidArgumentException if invalid operator is given.
140 *
141 * @return bool
142 */
143 public function versionCompare($a, $b, $operator, $compareBranches = false)
144 {
145 if (!isset(self::$transOpStr[$operator])) {
146 throw new \InvalidArgumentException(sprintf(
147 'Invalid operator "%s" given, expected one of: %s',
148 $operator,
149 implode(', ', self::getSupportedOperators())
150 ));
151 }
152
153 $aIsBranch = 'dev-' === substr($a, 0, 4);
154 $bIsBranch = 'dev-' === substr($b, 0, 4);
155
156 if ($aIsBranch && $bIsBranch) {
157 return $operator === '==' && $a === $b;
158 }
159
160 // when branches are not comparable, we make sure dev branches never match anything
161 if (!$compareBranches && ($aIsBranch || $bIsBranch)) {
162 return false;
163 }
164
165 return version_compare($a, $b, $operator);
166 }
167
168 /**
169 * @param Constraint $provider
170 * @param bool $compareBranches
171 *
172 * @return bool
173 */
174 public function matchSpecific(Constraint $provider, $compareBranches = false)
175 {
176 $noEqualOp = str_replace('=', '', self::$transOpInt[$this->operator]);
177 $providerNoEqualOp = str_replace('=', '', self::$transOpInt[$provider->operator]);
178
179 $isEqualOp = self::OP_EQ === $this->operator;
180 $isNonEqualOp = self::OP_NE === $this->operator;
181 $isProviderEqualOp = self::OP_EQ === $provider->operator;
182 $isProviderNonEqualOp = self::OP_NE === $provider->operator;
183
184 // '!=' operator is match when other operator is not '==' operator or version is not match
185 // these kinds of comparisons always have a solution
186 if ($isNonEqualOp || $isProviderNonEqualOp) {
187 return !$isEqualOp && !$isProviderEqualOp
188 || $this->versionCompare($provider->version, $this->version, '!=', $compareBranches);
189 }
190
191 // an example for the condition is <= 2.0 & < 1.0
192 // these kinds of comparisons always have a solution
193 if ($this->operator !== self::OP_EQ && $noEqualOp === $providerNoEqualOp) {
194 return true;
195 }
196
197 if ($this->versionCompare($provider->version, $this->version, self::$transOpInt[$this->operator], $compareBranches)) {
198 // special case, e.g. require >= 1.0 and provide < 1.0
199 // 1.0 >= 1.0 but 1.0 is outside of the provided interval
200 if ($provider->version === $this->version
201 && self::$transOpInt[$provider->operator] === $providerNoEqualOp
202 && self::$transOpInt[$this->operator] !== $noEqualOp) {
203 return false;
204 }
205
206 return true;
207 }
208
209 return false;
210 }
211
212 /**
213 * @return string
214 */
215 public function __toString()
216 {
217 return self::$transOpInt[$this->operator] . ' ' . $this->version;
218 }
219 }