PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 5.8.2
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v5.8.2
5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / app / vendor / composer / semver / src / Constraint / Constraint.php
matomo / app / vendor / composer / semver / src / Constraint Last commit date
Bound.php 1 year ago Constraint.php 1 year ago ConstraintInterface.php 1 year ago MatchAllConstraint.php 1 year ago MatchNoneConstraint.php 1 year ago MultiConstraint.php 1 year ago
Constraint.php
436 lines
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 /* operator string values */
28 const STR_OP_EQ = '==';
29 const STR_OP_EQ_ALT = '=';
30 const STR_OP_LT = '<';
31 const STR_OP_LE = '<=';
32 const STR_OP_GT = '>';
33 const STR_OP_GE = '>=';
34 const STR_OP_NE = '!=';
35 const STR_OP_NE_ALT = '<>';
36
37 /**
38 * Operator to integer translation table.
39 *
40 * @var array
41 * @phpstan-var array<self::STR_OP_*, self::OP_*>
42 */
43 private static $transOpStr = array(
44 '=' => self::OP_EQ,
45 '==' => self::OP_EQ,
46 '<' => self::OP_LT,
47 '<=' => self::OP_LE,
48 '>' => self::OP_GT,
49 '>=' => self::OP_GE,
50 '<>' => self::OP_NE,
51 '!=' => self::OP_NE,
52 );
53
54 /**
55 * Integer to operator translation table.
56 *
57 * @var array
58 * @phpstan-var array<self::OP_*, self::STR_OP_*>
59 */
60 private static $transOpInt = array(
61 self::OP_EQ => '==',
62 self::OP_LT => '<',
63 self::OP_LE => '<=',
64 self::OP_GT => '>',
65 self::OP_GE => '>=',
66 self::OP_NE => '!=',
67 );
68
69 /**
70 * @var int
71 * @phpstan-var self::OP_*
72 */
73 protected $operator;
74
75 /** @var string */
76 protected $version;
77
78 /** @var string|null */
79 protected $prettyString;
80
81 /** @var Bound */
82 protected $lowerBound;
83
84 /** @var Bound */
85 protected $upperBound;
86
87 /**
88 * Sets operator and version to compare with.
89 *
90 * @param string $operator
91 * @param string $version
92 *
93 * @throws \InvalidArgumentException if invalid operator is given.
94 *
95 * @phpstan-param self::STR_OP_* $operator
96 */
97 public function __construct($operator, $version)
98 {
99 if (!isset(self::$transOpStr[$operator])) {
100 throw new \InvalidArgumentException(sprintf(
101 'Invalid operator "%s" given, expected one of: %s',
102 $operator,
103 implode(', ', self::getSupportedOperators())
104 ));
105 }
106
107 $this->operator = self::$transOpStr[$operator];
108 $this->version = $version;
109 }
110
111 /**
112 * @return string
113 */
114 public function getVersion()
115 {
116 return $this->version;
117 }
118
119 /**
120 * @return string
121 *
122 * @phpstan-return self::STR_OP_*
123 */
124 public function getOperator()
125 {
126 return self::$transOpInt[$this->operator];
127 }
128
129 /**
130 * @param ConstraintInterface $provider
131 *
132 * @return bool
133 */
134 public function matches(ConstraintInterface $provider)
135 {
136 if ($provider instanceof self) {
137 return $this->matchSpecific($provider);
138 }
139
140 // turn matching around to find a match
141 return $provider->matches($this);
142 }
143
144 /**
145 * {@inheritDoc}
146 */
147 public function setPrettyString($prettyString)
148 {
149 $this->prettyString = $prettyString;
150 }
151
152 /**
153 * {@inheritDoc}
154 */
155 public function getPrettyString()
156 {
157 if ($this->prettyString) {
158 return $this->prettyString;
159 }
160
161 return $this->__toString();
162 }
163
164 /**
165 * Get all supported comparison operators.
166 *
167 * @return array
168 *
169 * @phpstan-return list<self::STR_OP_*>
170 */
171 public static function getSupportedOperators()
172 {
173 return array_keys(self::$transOpStr);
174 }
175
176 /**
177 * @param string $operator
178 * @return int
179 *
180 * @phpstan-param self::STR_OP_* $operator
181 * @phpstan-return self::OP_*
182 */
183 public static function getOperatorConstant($operator)
184 {
185 return self::$transOpStr[$operator];
186 }
187
188 /**
189 * @param string $a
190 * @param string $b
191 * @param string $operator
192 * @param bool $compareBranches
193 *
194 * @throws \InvalidArgumentException if invalid operator is given.
195 *
196 * @return bool
197 *
198 * @phpstan-param self::STR_OP_* $operator
199 */
200 public function versionCompare($a, $b, $operator, $compareBranches = false)
201 {
202 if (!isset(self::$transOpStr[$operator])) {
203 throw new \InvalidArgumentException(sprintf(
204 'Invalid operator "%s" given, expected one of: %s',
205 $operator,
206 implode(', ', self::getSupportedOperators())
207 ));
208 }
209
210 $aIsBranch = strpos($a, 'dev-') === 0;
211 $bIsBranch = strpos($b, 'dev-') === 0;
212
213 if ($operator === '!=' && ($aIsBranch || $bIsBranch)) {
214 return $a !== $b;
215 }
216
217 if ($aIsBranch && $bIsBranch) {
218 return $operator === '==' && $a === $b;
219 }
220
221 // when branches are not comparable, we make sure dev branches never match anything
222 if (!$compareBranches && ($aIsBranch || $bIsBranch)) {
223 return false;
224 }
225
226 return \version_compare($a, $b, $operator);
227 }
228
229 /**
230 * {@inheritDoc}
231 */
232 public function compile($otherOperator)
233 {
234 if (strpos($this->version, 'dev-') === 0) {
235 if (self::OP_EQ === $this->operator) {
236 if (self::OP_EQ === $otherOperator) {
237 return sprintf('$b && $v === %s', \var_export($this->version, true));
238 }
239 if (self::OP_NE === $otherOperator) {
240 return sprintf('!$b || $v !== %s', \var_export($this->version, true));
241 }
242 return 'false';
243 }
244
245 if (self::OP_NE === $this->operator) {
246 if (self::OP_EQ === $otherOperator) {
247 return sprintf('!$b || $v !== %s', \var_export($this->version, true));
248 }
249 if (self::OP_NE === $otherOperator) {
250 return 'true';
251 }
252 return '!$b';
253 }
254
255 return 'false';
256 }
257
258 if (self::OP_EQ === $this->operator) {
259 if (self::OP_EQ === $otherOperator) {
260 return sprintf('\version_compare($v, %s, \'==\')', \var_export($this->version, true));
261 }
262 if (self::OP_NE === $otherOperator) {
263 return sprintf('$b || \version_compare($v, %s, \'!=\')', \var_export($this->version, true));
264 }
265
266 return sprintf('!$b && \version_compare(%s, $v, \'%s\')', \var_export($this->version, true), self::$transOpInt[$otherOperator]);
267 }
268
269 if (self::OP_NE === $this->operator) {
270 if (self::OP_EQ === $otherOperator) {
271 return sprintf('$b || (!$b && \version_compare($v, %s, \'!=\'))', \var_export($this->version, true));
272 }
273
274 if (self::OP_NE === $otherOperator) {
275 return 'true';
276 }
277 return '!$b';
278 }
279
280 if (self::OP_LT === $this->operator || self::OP_LE === $this->operator) {
281 if (self::OP_LT === $otherOperator || self::OP_LE === $otherOperator) {
282 return '!$b';
283 }
284 } else { // $this->operator must be self::OP_GT || self::OP_GE here
285 if (self::OP_GT === $otherOperator || self::OP_GE === $otherOperator) {
286 return '!$b';
287 }
288 }
289
290 if (self::OP_NE === $otherOperator) {
291 return 'true';
292 }
293
294 $codeComparison = sprintf('\version_compare($v, %s, \'%s\')', \var_export($this->version, true), self::$transOpInt[$this->operator]);
295 if ($this->operator === self::OP_LE) {
296 if ($otherOperator === self::OP_GT) {
297 return sprintf('!$b && \version_compare($v, %s, \'!=\') && ', \var_export($this->version, true)) . $codeComparison;
298 }
299 } elseif ($this->operator === self::OP_GE) {
300 if ($otherOperator === self::OP_LT) {
301 return sprintf('!$b && \version_compare($v, %s, \'!=\') && ', \var_export($this->version, true)) . $codeComparison;
302 }
303 }
304
305 return sprintf('!$b && %s', $codeComparison);
306 }
307
308 /**
309 * @param Constraint $provider
310 * @param bool $compareBranches
311 *
312 * @return bool
313 */
314 public function matchSpecific(Constraint $provider, $compareBranches = false)
315 {
316 $noEqualOp = str_replace('=', '', self::$transOpInt[$this->operator]);
317 $providerNoEqualOp = str_replace('=', '', self::$transOpInt[$provider->operator]);
318
319 $isEqualOp = self::OP_EQ === $this->operator;
320 $isNonEqualOp = self::OP_NE === $this->operator;
321 $isProviderEqualOp = self::OP_EQ === $provider->operator;
322 $isProviderNonEqualOp = self::OP_NE === $provider->operator;
323
324 // '!=' operator is match when other operator is not '==' operator or version is not match
325 // these kinds of comparisons always have a solution
326 if ($isNonEqualOp || $isProviderNonEqualOp) {
327 if ($isNonEqualOp && !$isProviderNonEqualOp && !$isProviderEqualOp && strpos($provider->version, 'dev-') === 0) {
328 return false;
329 }
330
331 if ($isProviderNonEqualOp && !$isNonEqualOp && !$isEqualOp && strpos($this->version, 'dev-') === 0) {
332 return false;
333 }
334
335 if (!$isEqualOp && !$isProviderEqualOp) {
336 return true;
337 }
338 return $this->versionCompare($provider->version, $this->version, '!=', $compareBranches);
339 }
340
341 // an example for the condition is <= 2.0 & < 1.0
342 // these kinds of comparisons always have a solution
343 if ($this->operator !== self::OP_EQ && $noEqualOp === $providerNoEqualOp) {
344 return !(strpos($this->version, 'dev-') === 0 || strpos($provider->version, 'dev-') === 0);
345 }
346
347 $version1 = $isEqualOp ? $this->version : $provider->version;
348 $version2 = $isEqualOp ? $provider->version : $this->version;
349 $operator = $isEqualOp ? $provider->operator : $this->operator;
350
351 if ($this->versionCompare($version1, $version2, self::$transOpInt[$operator], $compareBranches)) {
352 // special case, e.g. require >= 1.0 and provide < 1.0
353 // 1.0 >= 1.0 but 1.0 is outside of the provided interval
354
355 return !(self::$transOpInt[$provider->operator] === $providerNoEqualOp
356 && self::$transOpInt[$this->operator] !== $noEqualOp
357 && \version_compare($provider->version, $this->version, '=='));
358 }
359
360 return false;
361 }
362
363 /**
364 * @return string
365 */
366 public function __toString()
367 {
368 return self::$transOpInt[$this->operator] . ' ' . $this->version;
369 }
370
371 /**
372 * {@inheritDoc}
373 */
374 public function getLowerBound()
375 {
376 $this->extractBounds();
377
378 return $this->lowerBound;
379 }
380
381 /**
382 * {@inheritDoc}
383 */
384 public function getUpperBound()
385 {
386 $this->extractBounds();
387
388 return $this->upperBound;
389 }
390
391 /**
392 * @return void
393 */
394 private function extractBounds()
395 {
396 if (null !== $this->lowerBound) {
397 return;
398 }
399
400 // Branches
401 if (strpos($this->version, 'dev-') === 0) {
402 $this->lowerBound = Bound::zero();
403 $this->upperBound = Bound::positiveInfinity();
404
405 return;
406 }
407
408 switch ($this->operator) {
409 case self::OP_EQ:
410 $this->lowerBound = new Bound($this->version, true);
411 $this->upperBound = new Bound($this->version, true);
412 break;
413 case self::OP_LT:
414 $this->lowerBound = Bound::zero();
415 $this->upperBound = new Bound($this->version, false);
416 break;
417 case self::OP_LE:
418 $this->lowerBound = Bound::zero();
419 $this->upperBound = new Bound($this->version, true);
420 break;
421 case self::OP_GT:
422 $this->lowerBound = new Bound($this->version, false);
423 $this->upperBound = Bound::positiveInfinity();
424 break;
425 case self::OP_GE:
426 $this->lowerBound = new Bound($this->version, true);
427 $this->upperBound = Bound::positiveInfinity();
428 break;
429 case self::OP_NE:
430 $this->lowerBound = Bound::zero();
431 $this->upperBound = Bound::positiveInfinity();
432 break;
433 }
434 }
435 }
436