7a21eb47f5446207d6aef3260d3e663124915c72
[yaffs-website] / vendor / composer / semver / src / Constraint / Constraint.php
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 }