Completed
Push — develop ( 0e25c3...d044f3 )
by Zack
16:03
created
vendor/phpdocumentor/type-resolver/src/PseudoTypes/IntegerRange.php 1 patch
Indentation   +34 added lines, -34 removed lines patch added patch discarded remove patch
@@ -24,38 +24,38 @@
 block discarded – undo
24 24
  */
25 25
 final class IntegerRange extends Integer implements PseudoType
26 26
 {
27
-    /** @var string */
28
-    private $minValue;
29
-
30
-    /** @var string */
31
-    private $maxValue;
32
-
33
-    public function __construct(string $minValue, string $maxValue)
34
-    {
35
-        $this->minValue = $minValue;
36
-        $this->maxValue = $maxValue;
37
-    }
38
-
39
-    public function underlyingType(): Type
40
-    {
41
-        return new Integer();
42
-    }
43
-
44
-    public function getMinValue(): string
45
-    {
46
-        return $this->minValue;
47
-    }
48
-
49
-    public function getMaxValue(): string
50
-    {
51
-        return $this->maxValue;
52
-    }
53
-
54
-    /**
55
-     * Returns a rendered output of the Type as it would be used in a DocBlock.
56
-     */
57
-    public function __toString(): string
58
-    {
59
-        return 'int<' . $this->minValue . ', ' . $this->maxValue . '>';
60
-    }
27
+	/** @var string */
28
+	private $minValue;
29
+
30
+	/** @var string */
31
+	private $maxValue;
32
+
33
+	public function __construct(string $minValue, string $maxValue)
34
+	{
35
+		$this->minValue = $minValue;
36
+		$this->maxValue = $maxValue;
37
+	}
38
+
39
+	public function underlyingType(): Type
40
+	{
41
+		return new Integer();
42
+	}
43
+
44
+	public function getMinValue(): string
45
+	{
46
+		return $this->minValue;
47
+	}
48
+
49
+	public function getMaxValue(): string
50
+	{
51
+		return $this->maxValue;
52
+	}
53
+
54
+	/**
55
+	 * Returns a rendered output of the Type as it would be used in a DocBlock.
56
+	 */
57
+	public function __toString(): string
58
+	{
59
+		return 'int<' . $this->minValue . ', ' . $this->maxValue . '>';
60
+	}
61 61
 }
Please login to merge, or discard this patch.
vendor/phpdocumentor/type-resolver/src/PseudoTypes/List_.php 1 patch
Indentation   +21 added lines, -21 removed lines patch added patch discarded remove patch
@@ -26,25 +26,25 @@
 block discarded – undo
26 26
  */
27 27
 final class List_ extends Array_ implements PseudoType
28 28
 {
29
-    public function underlyingType(): Type
30
-    {
31
-        return new Array_();
32
-    }
33
-
34
-    public function __construct(?Type $valueType = null)
35
-    {
36
-        parent::__construct($valueType, new Integer());
37
-    }
38
-
39
-    /**
40
-     * Returns a rendered output of the Type as it would be used in a DocBlock.
41
-     */
42
-    public function __toString(): string
43
-    {
44
-        if ($this->valueType instanceof Mixed_) {
45
-            return 'list';
46
-        }
47
-
48
-        return 'list<' . $this->valueType . '>';
49
-    }
29
+	public function underlyingType(): Type
30
+	{
31
+		return new Array_();
32
+	}
33
+
34
+	public function __construct(?Type $valueType = null)
35
+	{
36
+		parent::__construct($valueType, new Integer());
37
+	}
38
+
39
+	/**
40
+	 * Returns a rendered output of the Type as it would be used in a DocBlock.
41
+	 */
42
+	public function __toString(): string
43
+	{
44
+		if ($this->valueType instanceof Mixed_) {
45
+			return 'list';
46
+		}
47
+
48
+		return 'list<' . $this->valueType . '>';
49
+	}
50 50
 }
Please login to merge, or discard this patch.
vendor/doctrine/inflector/lib/Doctrine/Common/Inflector/Inflector.php 1 patch
Indentation   +209 added lines, -209 removed lines patch added patch discarded remove patch
@@ -44,241 +44,241 @@
 block discarded – undo
44 44
  */
45 45
 class Inflector
46 46
 {
47
-    /**
48
-     * @var LanguageInflectorFactory|null
49
-     */
50
-    private static $factory;
47
+	/**
48
+	 * @var LanguageInflectorFactory|null
49
+	 */
50
+	private static $factory;
51 51
 
52
-    /** @var InflectorObject|null */
53
-    private static $instance;
52
+	/** @var InflectorObject|null */
53
+	private static $instance;
54 54
 
55
-    private static function getInstance() : InflectorObject
56
-    {
57
-        if (self::$factory === null) {
58
-            self::$factory = self::createFactory();
59
-        }
55
+	private static function getInstance() : InflectorObject
56
+	{
57
+		if (self::$factory === null) {
58
+			self::$factory = self::createFactory();
59
+		}
60 60
 
61
-        if (self::$instance === null) {
62
-            self::$instance = self::$factory->build();
63
-        }
61
+		if (self::$instance === null) {
62
+			self::$instance = self::$factory->build();
63
+		}
64 64
 
65
-        return self::$instance;
66
-    }
65
+		return self::$instance;
66
+	}
67 67
 
68
-    private static function createFactory() : LanguageInflectorFactory
69
-    {
70
-        return InflectorFactory::create();
71
-    }
68
+	private static function createFactory() : LanguageInflectorFactory
69
+	{
70
+		return InflectorFactory::create();
71
+	}
72 72
 
73
-    /**
74
-     * Converts a word into the format for a Doctrine table name. Converts 'ModelName' to 'model_name'.
75
-     *
76
-     * @deprecated
77
-     */
78
-    public static function tableize(string $word) : string
79
-    {
80
-        @trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.', __METHOD__), E_USER_DEPRECATED);
73
+	/**
74
+	 * Converts a word into the format for a Doctrine table name. Converts 'ModelName' to 'model_name'.
75
+	 *
76
+	 * @deprecated
77
+	 */
78
+	public static function tableize(string $word) : string
79
+	{
80
+		@trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.', __METHOD__), E_USER_DEPRECATED);
81 81
 
82
-        return self::getInstance()->tableize($word);
83
-    }
82
+		return self::getInstance()->tableize($word);
83
+	}
84 84
 
85
-    /**
86
-     * Converts a word into the format for a Doctrine class name. Converts 'table_name' to 'TableName'.
87
-     */
88
-    public static function classify(string $word) : string
89
-    {
90
-        @trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.', __METHOD__), E_USER_DEPRECATED);
85
+	/**
86
+	 * Converts a word into the format for a Doctrine class name. Converts 'table_name' to 'TableName'.
87
+	 */
88
+	public static function classify(string $word) : string
89
+	{
90
+		@trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.', __METHOD__), E_USER_DEPRECATED);
91 91
 
92
-        return self::getInstance()->classify($word);
93
-    }
92
+		return self::getInstance()->classify($word);
93
+	}
94 94
 
95
-    /**
96
-     * Camelizes a word. This uses the classify() method and turns the first character to lowercase.
97
-     *
98
-     * @deprecated
99
-     */
100
-    public static function camelize(string $word) : string
101
-    {
102
-        @trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.', __METHOD__), E_USER_DEPRECATED);
95
+	/**
96
+	 * Camelizes a word. This uses the classify() method and turns the first character to lowercase.
97
+	 *
98
+	 * @deprecated
99
+	 */
100
+	public static function camelize(string $word) : string
101
+	{
102
+		@trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.', __METHOD__), E_USER_DEPRECATED);
103 103
 
104
-        return self::getInstance()->camelize($word);
105
-    }
104
+		return self::getInstance()->camelize($word);
105
+	}
106 106
 
107
-    /**
108
-     * Uppercases words with configurable delimiters between words.
109
-     *
110
-     * Takes a string and capitalizes all of the words, like PHP's built-in
111
-     * ucwords function. This extends that behavior, however, by allowing the
112
-     * word delimiters to be configured, rather than only separating on
113
-     * whitespace.
114
-     *
115
-     * Here is an example:
116
-     * <code>
117
-     * <?php
118
-     * $string = 'top-o-the-morning to all_of_you!';
119
-     * echo \Doctrine\Common\Inflector\Inflector::ucwords($string);
120
-     * // Top-O-The-Morning To All_of_you!
121
-     *
122
-     * echo \Doctrine\Common\Inflector\Inflector::ucwords($string, '-_ ');
123
-     * // Top-O-The-Morning To All_Of_You!
124
-     * ?>
125
-     * </code>
126
-     *
127
-     * @param string $string The string to operate on.
128
-     * @param string $delimiters A list of word separators.
129
-     *
130
-     * @return string The string with all delimiter-separated words capitalized.
131
-     *
132
-     * @deprecated
133
-     */
134
-    public static function ucwords(string $string, string $delimiters = " \n\t\r\0\x0B-") : string
135
-    {
136
-        @trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please use the "ucwords" function instead.', __METHOD__), E_USER_DEPRECATED);
107
+	/**
108
+	 * Uppercases words with configurable delimiters between words.
109
+	 *
110
+	 * Takes a string and capitalizes all of the words, like PHP's built-in
111
+	 * ucwords function. This extends that behavior, however, by allowing the
112
+	 * word delimiters to be configured, rather than only separating on
113
+	 * whitespace.
114
+	 *
115
+	 * Here is an example:
116
+	 * <code>
117
+	 * <?php
118
+	 * $string = 'top-o-the-morning to all_of_you!';
119
+	 * echo \Doctrine\Common\Inflector\Inflector::ucwords($string);
120
+	 * // Top-O-The-Morning To All_of_you!
121
+	 *
122
+	 * echo \Doctrine\Common\Inflector\Inflector::ucwords($string, '-_ ');
123
+	 * // Top-O-The-Morning To All_Of_You!
124
+	 * ?>
125
+	 * </code>
126
+	 *
127
+	 * @param string $string The string to operate on.
128
+	 * @param string $delimiters A list of word separators.
129
+	 *
130
+	 * @return string The string with all delimiter-separated words capitalized.
131
+	 *
132
+	 * @deprecated
133
+	 */
134
+	public static function ucwords(string $string, string $delimiters = " \n\t\r\0\x0B-") : string
135
+	{
136
+		@trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please use the "ucwords" function instead.', __METHOD__), E_USER_DEPRECATED);
137 137
 
138
-        return ucwords($string, $delimiters);
139
-    }
138
+		return ucwords($string, $delimiters);
139
+	}
140 140
 
141
-    /**
142
-     * Clears Inflectors inflected value caches, and resets the inflection
143
-     * rules to the initial values.
144
-     *
145
-     * @deprecated
146
-     */
147
-    public static function reset() : void
148
-    {
149
-        @trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.', __METHOD__), E_USER_DEPRECATED);
141
+	/**
142
+	 * Clears Inflectors inflected value caches, and resets the inflection
143
+	 * rules to the initial values.
144
+	 *
145
+	 * @deprecated
146
+	 */
147
+	public static function reset() : void
148
+	{
149
+		@trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.', __METHOD__), E_USER_DEPRECATED);
150 150
 
151
-        self::$factory = null;
152
-        self::$instance = null;
153
-    }
151
+		self::$factory = null;
152
+		self::$instance = null;
153
+	}
154 154
 
155
-    /**
156
-     * Adds custom inflection $rules, of either 'plural' or 'singular' $type.
157
-     *
158
-     * ### Usage:
159
-     *
160
-     * {{{
161
-     * Inflector::rules('plural', array('/^(inflect)or$/i' => '\1ables'));
162
-     * Inflector::rules('plural', array(
163
-     *     'rules' => array('/^(inflect)ors$/i' => '\1ables'),
164
-     *     'uninflected' => array('dontinflectme'),
165
-     *     'irregular' => array('red' => 'redlings')
166
-     * ));
167
-     * }}}
168
-     *
169
-     * @param string  $type         The type of inflection, either 'plural' or 'singular'
170
-     * @param array<string,mixed>|iterable<string,mixed> $rules An array of rules to be added.
171
-     * @param boolean $reset        If true, will unset default inflections for all
172
-     *                              new rules that are being defined in $rules.
173
-     *
174
-     * @return void
175
-     *
176
-     * @deprecated
177
-     */
178
-    public static function rules(string $type, iterable $rules, bool $reset = false) : void
179
-    {
180
-        @trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.', __METHOD__), E_USER_DEPRECATED);
155
+	/**
156
+	 * Adds custom inflection $rules, of either 'plural' or 'singular' $type.
157
+	 *
158
+	 * ### Usage:
159
+	 *
160
+	 * {{{
161
+	 * Inflector::rules('plural', array('/^(inflect)or$/i' => '\1ables'));
162
+	 * Inflector::rules('plural', array(
163
+	 *     'rules' => array('/^(inflect)ors$/i' => '\1ables'),
164
+	 *     'uninflected' => array('dontinflectme'),
165
+	 *     'irregular' => array('red' => 'redlings')
166
+	 * ));
167
+	 * }}}
168
+	 *
169
+	 * @param string  $type         The type of inflection, either 'plural' or 'singular'
170
+	 * @param array<string,mixed>|iterable<string,mixed> $rules An array of rules to be added.
171
+	 * @param boolean $reset        If true, will unset default inflections for all
172
+	 *                              new rules that are being defined in $rules.
173
+	 *
174
+	 * @return void
175
+	 *
176
+	 * @deprecated
177
+	 */
178
+	public static function rules(string $type, iterable $rules, bool $reset = false) : void
179
+	{
180
+		@trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.', __METHOD__), E_USER_DEPRECATED);
181 181
 
182
-        if (self::$factory === null) {
183
-            self::$factory = self::createFactory();
184
-        }
182
+		if (self::$factory === null) {
183
+			self::$factory = self::createFactory();
184
+		}
185 185
 
186
-        self::$instance = null;
186
+		self::$instance = null;
187 187
 
188
-        switch ($type) {
189
-            case 'singular':
190
-                self::$factory->withSingularRules(self::buildRuleset($rules), $reset);
191
-                break;
192
-            case 'plural':
193
-                self::$factory->withPluralRules(self::buildRuleset($rules), $reset);
194
-                break;
195
-            default:
196
-                throw new InvalidArgumentException(sprintf('Cannot define custom inflection rules for type "%s".', $type));
197
-        }
198
-    }
188
+		switch ($type) {
189
+			case 'singular':
190
+				self::$factory->withSingularRules(self::buildRuleset($rules), $reset);
191
+				break;
192
+			case 'plural':
193
+				self::$factory->withPluralRules(self::buildRuleset($rules), $reset);
194
+				break;
195
+			default:
196
+				throw new InvalidArgumentException(sprintf('Cannot define custom inflection rules for type "%s".', $type));
197
+		}
198
+	}
199 199
 
200
-    /**
201
-      * @param array<string,mixed>|iterable<string,mixed> $rules An array of rules to be added.
202
-      */
203
-    private static function buildRuleset(iterable $rules) : Ruleset
204
-    {
205
-        $regular = [];
206
-        $irregular = [];
207
-        $uninflected = [];
200
+	/**
201
+	 * @param array<string,mixed>|iterable<string,mixed> $rules An array of rules to be added.
202
+	 */
203
+	private static function buildRuleset(iterable $rules) : Ruleset
204
+	{
205
+		$regular = [];
206
+		$irregular = [];
207
+		$uninflected = [];
208 208
 
209
-        foreach ($rules as $rule => $pattern) {
210
-            if ( ! is_array($pattern)) {
211
-                $regular[$rule] = $pattern;
209
+		foreach ($rules as $rule => $pattern) {
210
+			if ( ! is_array($pattern)) {
211
+				$regular[$rule] = $pattern;
212 212
 
213
-                continue;
214
-            }
213
+				continue;
214
+			}
215 215
 
216
-            switch ($rule) {
217
-                case 'uninflected':
218
-                    $uninflected = $pattern;
219
-                    break;
220
-                case 'irregular':
221
-                    $irregular = $pattern;
222
-                    break;
223
-                case 'rules':
224
-                    $regular = $pattern;
225
-                    break;
226
-            }
227
-        }
216
+			switch ($rule) {
217
+				case 'uninflected':
218
+					$uninflected = $pattern;
219
+					break;
220
+				case 'irregular':
221
+					$irregular = $pattern;
222
+					break;
223
+				case 'rules':
224
+					$regular = $pattern;
225
+					break;
226
+			}
227
+		}
228 228
 
229
-        return new Ruleset(
230
-            new Transformations(...array_map(
231
-                static function (string $pattern, string $replacement) : Transformation {
232
-                    return new Transformation(new Pattern($pattern), $replacement);
233
-                },
234
-                array_keys($regular),
235
-                array_values($regular)
236
-            )),
237
-            new Patterns(...array_map(
238
-                static function (string $pattern) : Pattern {
239
-                    return new Pattern($pattern);
240
-                },
241
-                $uninflected
242
-            )),
243
-            new Substitutions(...array_map(
244
-                static function (string $word, string $to) : Substitution {
245
-                    return new Substitution(new Word($word), new Word($to));
246
-                },
247
-                array_keys($irregular),
248
-                array_values($irregular)
249
-            ))
250
-        );
251
-    }
229
+		return new Ruleset(
230
+			new Transformations(...array_map(
231
+				static function (string $pattern, string $replacement) : Transformation {
232
+					return new Transformation(new Pattern($pattern), $replacement);
233
+				},
234
+				array_keys($regular),
235
+				array_values($regular)
236
+			)),
237
+			new Patterns(...array_map(
238
+				static function (string $pattern) : Pattern {
239
+					return new Pattern($pattern);
240
+				},
241
+				$uninflected
242
+			)),
243
+			new Substitutions(...array_map(
244
+				static function (string $word, string $to) : Substitution {
245
+					return new Substitution(new Word($word), new Word($to));
246
+				},
247
+				array_keys($irregular),
248
+				array_values($irregular)
249
+			))
250
+		);
251
+	}
252 252
 
253
-    /**
254
-     * Returns a word in plural form.
255
-     *
256
-     * @param string $word The word in singular form.
257
-     *
258
-     * @return string The word in plural form.
259
-     *
260
-     * @deprecated
261
-     */
262
-    public static function pluralize(string $word) : string
263
-    {
264
-        @trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.', __METHOD__), E_USER_DEPRECATED);
253
+	/**
254
+	 * Returns a word in plural form.
255
+	 *
256
+	 * @param string $word The word in singular form.
257
+	 *
258
+	 * @return string The word in plural form.
259
+	 *
260
+	 * @deprecated
261
+	 */
262
+	public static function pluralize(string $word) : string
263
+	{
264
+		@trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.', __METHOD__), E_USER_DEPRECATED);
265 265
 
266
-        return self::getInstance()->pluralize($word);
267
-    }
266
+		return self::getInstance()->pluralize($word);
267
+	}
268 268
 
269
-    /**
270
-     * Returns a word in singular form.
271
-     *
272
-     * @param string $word The word in plural form.
273
-     *
274
-     * @return string The word in singular form.
275
-     *
276
-     * @deprecated
277
-     */
278
-    public static function singularize(string $word) : string
279
-    {
280
-        @trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.', __METHOD__), E_USER_DEPRECATED);
269
+	/**
270
+	 * Returns a word in singular form.
271
+	 *
272
+	 * @param string $word The word in plural form.
273
+	 *
274
+	 * @return string The word in singular form.
275
+	 *
276
+	 * @deprecated
277
+	 */
278
+	public static function singularize(string $word) : string
279
+	{
280
+		@trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.', __METHOD__), E_USER_DEPRECATED);
281 281
 
282
-        return self::getInstance()->singularize($word);
283
-    }
282
+		return self::getInstance()->singularize($word);
283
+	}
284 284
 }
Please login to merge, or discard this patch.
vendor/composer/composer/src/Composer/DependencyResolver/PoolOptimizer.php 1 patch
Indentation   +420 added lines, -420 removed lines patch added patch discarded remove patch
@@ -28,424 +28,424 @@
 block discarded – undo
28 28
  */
29 29
 class PoolOptimizer
30 30
 {
31
-    /**
32
-     * @var PolicyInterface
33
-     */
34
-    private $policy;
35
-
36
-    /**
37
-     * @var array<int, true>
38
-     */
39
-    private $irremovablePackages = array();
40
-
41
-    /**
42
-     * @var array<string, array<string, ConstraintInterface>>
43
-     */
44
-    private $requireConstraintsPerPackage = array();
45
-
46
-    /**
47
-     * @var array<string, array<string, ConstraintInterface>>
48
-     */
49
-    private $conflictConstraintsPerPackage = array();
50
-
51
-    /**
52
-     * @var array<int, true>
53
-     */
54
-    private $packagesToRemove = array();
55
-
56
-    /**
57
-     * @var array<int, BasePackage[]>
58
-     */
59
-    private $aliasesPerPackage = array();
60
-
61
-    /**
62
-     * @var array<string, array<string, string>>
63
-     */
64
-    private $removedVersionsByPackage = array();
65
-
66
-    public function __construct(PolicyInterface $policy)
67
-    {
68
-        $this->policy = $policy;
69
-    }
70
-
71
-    /**
72
-     * @return Pool
73
-     */
74
-    public function optimize(Request $request, Pool $pool)
75
-    {
76
-        $this->prepare($request, $pool);
77
-
78
-        $this->optimizeByIdenticalDependencies($request, $pool);
79
-
80
-        $this->optimizeImpossiblePackagesAway($request, $pool);
81
-
82
-        $optimizedPool = $this->applyRemovalsToPool($pool);
83
-
84
-        // No need to run this recursively at the moment
85
-        // because the current optimizations cannot provide
86
-        // even more gains when ran again. Might change
87
-        // in the future with additional optimizations.
88
-
89
-        $this->irremovablePackages = array();
90
-        $this->requireConstraintsPerPackage = array();
91
-        $this->conflictConstraintsPerPackage = array();
92
-        $this->packagesToRemove = array();
93
-        $this->aliasesPerPackage = array();
94
-        $this->removedVersionsByPackage = array();
95
-
96
-        return $optimizedPool;
97
-    }
98
-
99
-    /**
100
-     * @return void
101
-     */
102
-    private function prepare(Request $request, Pool $pool)
103
-    {
104
-        $irremovablePackageConstraintGroups = array();
105
-
106
-        // Mark fixed or locked packages as irremovable
107
-        foreach ($request->getFixedOrLockedPackages() as $package) {
108
-            $irremovablePackageConstraintGroups[$package->getName()][] = new Constraint('==', $package->getVersion());
109
-        }
110
-
111
-        // Extract requested package requirements
112
-        foreach ($request->getRequires() as $require => $constraint) {
113
-            $constraint = Intervals::compactConstraint($constraint);
114
-            $this->requireConstraintsPerPackage[$require][(string) $constraint] = $constraint;
115
-        }
116
-
117
-        // First pass over all packages to extract information and mark package constraints irremovable
118
-        foreach ($pool->getPackages() as $package) {
119
-            // Extract package requirements
120
-            foreach ($package->getRequires() as $link) {
121
-                $constraint = Intervals::compactConstraint($link->getConstraint());
122
-                $this->requireConstraintsPerPackage[$link->getTarget()][(string) $constraint] = $constraint;
123
-            }
124
-            // Extract package conflicts
125
-            foreach ($package->getConflicts() as $link) {
126
-                $constraint = Intervals::compactConstraint($link->getConstraint());
127
-                $this->conflictConstraintsPerPackage[$link->getTarget()][(string) $constraint] = $constraint;
128
-            }
129
-
130
-            // Keep track of alias packages for every package so if either the alias or aliased is kept
131
-            // we keep the others as they are a unit of packages really
132
-            if ($package instanceof AliasPackage) {
133
-                $this->aliasesPerPackage[$package->getAliasOf()->id][] = $package;
134
-            }
135
-        }
136
-
137
-        $irremovablePackageConstraints = array();
138
-        foreach ($irremovablePackageConstraintGroups as $packageName => $constraints) {
139
-            $irremovablePackageConstraints[$packageName] = 1 === \count($constraints) ? $constraints[0] : new MultiConstraint($constraints, false);
140
-        }
141
-        unset($irremovablePackageConstraintGroups);
142
-
143
-        // Mark the packages as irremovable based on the constraints
144
-        foreach ($pool->getPackages() as $package) {
145
-            if (!isset($irremovablePackageConstraints[$package->getName()])) {
146
-                continue;
147
-            }
148
-
149
-            if (CompilingMatcher::match($irremovablePackageConstraints[$package->getName()], Constraint::OP_EQ, $package->getVersion())) {
150
-                $this->markPackageIrremovable($package);
151
-            }
152
-        }
153
-    }
154
-
155
-    /**
156
-     * @return void
157
-     */
158
-    private function markPackageIrremovable(BasePackage $package)
159
-    {
160
-        $this->irremovablePackages[$package->id] = true;
161
-        if ($package instanceof AliasPackage) {
162
-            // recursing here so aliasesPerPackage for the aliasOf can be checked
163
-            // and all its aliases marked as irremovable as well
164
-            $this->markPackageIrremovable($package->getAliasOf());
165
-        }
166
-        if (isset($this->aliasesPerPackage[$package->id])) {
167
-            foreach ($this->aliasesPerPackage[$package->id] as $aliasPackage) {
168
-                $this->irremovablePackages[$aliasPackage->id] = true;
169
-            }
170
-        }
171
-    }
172
-
173
-    /**
174
-     * @return Pool Optimized pool
175
-     */
176
-    private function applyRemovalsToPool(Pool $pool)
177
-    {
178
-        $packages = array();
179
-        $removedVersions = array();
180
-        foreach ($pool->getPackages() as $package) {
181
-            if (!isset($this->packagesToRemove[$package->id])) {
182
-                $packages[] = $package;
183
-            } else {
184
-                $removedVersions[$package->getName()][$package->getVersion()] = $package->getPrettyVersion();
185
-            }
186
-        }
187
-
188
-        $optimizedPool = new Pool($packages, $pool->getUnacceptableFixedOrLockedPackages(), $removedVersions, $this->removedVersionsByPackage);
189
-
190
-        return $optimizedPool;
191
-    }
192
-
193
-    /**
194
-     * @return void
195
-     */
196
-    private function optimizeByIdenticalDependencies(Request $request, Pool $pool)
197
-    {
198
-        $identicalDefinitionsPerPackage = array();
199
-        $packageIdenticalDefinitionLookup = array();
200
-
201
-        foreach ($pool->getPackages() as $package) {
202
-
203
-            // If that package was already marked irremovable, we can skip
204
-            // the entire process for it
205
-            if (isset($this->irremovablePackages[$package->id])) {
206
-                continue;
207
-            }
208
-
209
-            $this->markPackageForRemoval($package->id);
210
-
211
-            $dependencyHash = $this->calculateDependencyHash($package);
212
-
213
-            foreach ($package->getNames(false) as $packageName) {
214
-
215
-                if (!isset($this->requireConstraintsPerPackage[$packageName])) {
216
-                    continue;
217
-                }
218
-
219
-                foreach ($this->requireConstraintsPerPackage[$packageName] as $requireConstraint) {
220
-                    $groupHashParts = array();
221
-
222
-                    if (CompilingMatcher::match($requireConstraint, Constraint::OP_EQ, $package->getVersion())) {
223
-                        $groupHashParts[] = 'require:' . (string) $requireConstraint;
224
-                    }
225
-
226
-                    if ($package->getReplaces()) {
227
-                        foreach ($package->getReplaces() as $link) {
228
-                            if (CompilingMatcher::match($link->getConstraint(), Constraint::OP_EQ, $package->getVersion())) {
229
-                                // Use the same hash part as the regular require hash because that's what the replacement does
230
-                                $groupHashParts[] = 'require:' . (string) $link->getConstraint();
231
-                            }
232
-                        }
233
-                    }
234
-
235
-                    if (isset($this->conflictConstraintsPerPackage[$packageName])) {
236
-                        foreach ($this->conflictConstraintsPerPackage[$packageName] as $conflictConstraint) {
237
-                            if (CompilingMatcher::match($conflictConstraint, Constraint::OP_EQ, $package->getVersion())) {
238
-                                $groupHashParts[] = 'conflict:' . (string) $conflictConstraint;
239
-                            }
240
-                        }
241
-                    }
242
-
243
-                    if (!$groupHashParts) {
244
-                        continue;
245
-                    }
246
-
247
-                    $groupHash = implode('', $groupHashParts);
248
-                    $identicalDefinitionsPerPackage[$packageName][$groupHash][$dependencyHash][] = $package;
249
-                    $packageIdenticalDefinitionLookup[$package->id][$packageName] = array('groupHash' => $groupHash, 'dependencyHash' => $dependencyHash);
250
-                }
251
-            }
252
-        }
253
-
254
-        foreach ($identicalDefinitionsPerPackage as $constraintGroups) {
255
-            foreach ($constraintGroups as $constraintGroup) {
256
-                foreach ($constraintGroup as $packages) {
257
-                    // Only one package in this constraint group has the same requirements, we're not allowed to remove that package
258
-                    if (1 === \count($packages)) {
259
-                        $this->keepPackage($packages[0], $identicalDefinitionsPerPackage, $packageIdenticalDefinitionLookup);
260
-                        continue;
261
-                    }
262
-
263
-                    // Otherwise we find out which one is the preferred package in this constraint group which is
264
-                    // then not allowed to be removed either
265
-                    $literals = array();
266
-
267
-                    foreach ($packages as $package) {
268
-                        $literals[] = $package->id;
269
-                    }
270
-
271
-                    foreach ($this->policy->selectPreferredPackages($pool, $literals) as $preferredLiteral) {
272
-                        $this->keepPackage($pool->literalToPackage($preferredLiteral), $identicalDefinitionsPerPackage, $packageIdenticalDefinitionLookup);
273
-                    }
274
-                }
275
-            }
276
-        }
277
-    }
278
-
279
-    /**
280
-     * @return string
281
-     */
282
-    private function calculateDependencyHash(BasePackage $package)
283
-    {
284
-        $hash = '';
285
-
286
-        $hashRelevantLinks = array(
287
-            'requires' => $package->getRequires(),
288
-            'conflicts' => $package->getConflicts(),
289
-            'replaces' => $package->getReplaces(),
290
-            'provides' => $package->getProvides()
291
-        );
292
-
293
-        foreach ($hashRelevantLinks as $key => $links) {
294
-            if (0 === \count($links)) {
295
-                continue;
296
-            }
297
-
298
-            // start new hash section
299
-            $hash .= $key . ':';
300
-
301
-            $subhash = array();
302
-
303
-            foreach ($links as $link) {
304
-                // To get the best dependency hash matches we should use Intervals::compactConstraint() here.
305
-                // However, the majority of projects are going to specify their constraints already pretty
306
-                // much in the best variant possible. In other words, we'd be wasting time here and it would actually hurt
307
-                // performance more than the additional few packages that could be filtered out would benefit the process.
308
-                $subhash[$link->getTarget()] = (string) $link->getConstraint();
309
-            }
310
-
311
-            // Sort for best result
312
-            ksort($subhash);
313
-
314
-            foreach ($subhash as $target => $constraint) {
315
-                $hash .= $target . '@' . $constraint;
316
-            }
317
-        }
318
-
319
-        return $hash;
320
-    }
321
-
322
-    /**
323
-     * @param int $id
324
-     * @return void
325
-     */
326
-    private function markPackageForRemoval($id)
327
-    {
328
-        // We are not allowed to remove packages if they have been marked as irremovable
329
-        if (isset($this->irremovablePackages[$id])) {
330
-            throw new \LogicException('Attempted removing a package which was previously marked irremovable');
331
-        }
332
-
333
-        $this->packagesToRemove[$id] = true;
334
-    }
335
-
336
-    /**
337
-     * @param array<string, array<string, array<string, list<BasePackage>>>> $identicalDefinitionsPerPackage
338
-     * @param array<int, array<string, array{groupHash: string, dependencyHash: string}>> $packageIdenticalDefinitionLookup
339
-     * @return void
340
-     */
341
-    private function keepPackage(BasePackage $package, $identicalDefinitionsPerPackage, $packageIdenticalDefinitionLookup)
342
-    {
343
-        unset($this->packagesToRemove[$package->id]);
344
-
345
-        if ($package instanceof AliasPackage) {
346
-            // recursing here so aliasesPerPackage for the aliasOf can be checked
347
-            // and all its aliases marked to be kept as well
348
-            $this->keepPackage($package->getAliasOf(), $identicalDefinitionsPerPackage, $packageIdenticalDefinitionLookup);
349
-        }
350
-
351
-        // record all the versions of the package group so we can list them later in Problem output
352
-        foreach ($package->getNames(false) as $name) {
353
-            if (isset($packageIdenticalDefinitionLookup[$package->id][$name])) {
354
-                $packageGroupPointers = $packageIdenticalDefinitionLookup[$package->id][$name];
355
-                $packageGroup = $identicalDefinitionsPerPackage[$name][$packageGroupPointers['groupHash']][$packageGroupPointers['dependencyHash']];
356
-                foreach ($packageGroup as $pkg) {
357
-                    if ($pkg instanceof AliasPackage && $pkg->getPrettyVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) {
358
-                        $pkg = $pkg->getAliasOf();
359
-                    }
360
-                    $this->removedVersionsByPackage[spl_object_hash($package)][$pkg->getVersion()] = $pkg->getPrettyVersion();
361
-                }
362
-            }
363
-        }
364
-
365
-        if (isset($this->aliasesPerPackage[$package->id])) {
366
-            foreach ($this->aliasesPerPackage[$package->id] as $aliasPackage) {
367
-                unset($this->packagesToRemove[$aliasPackage->id]);
368
-
369
-                // record all the versions of the package group so we can list them later in Problem output
370
-                foreach ($aliasPackage->getNames(false) as $name) {
371
-                    if (isset($packageIdenticalDefinitionLookup[$aliasPackage->id][$name])) {
372
-                        $packageGroupPointers = $packageIdenticalDefinitionLookup[$aliasPackage->id][$name];
373
-                        $packageGroup = $identicalDefinitionsPerPackage[$name][$packageGroupPointers['groupHash']][$packageGroupPointers['dependencyHash']];
374
-                        foreach ($packageGroup as $pkg) {
375
-                            if ($pkg instanceof AliasPackage && $pkg->getPrettyVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) {
376
-                                $pkg = $pkg->getAliasOf();
377
-                            }
378
-                            $this->removedVersionsByPackage[spl_object_hash($aliasPackage)][$pkg->getVersion()] = $pkg->getPrettyVersion();
379
-                        }
380
-                    }
381
-                }
382
-            }
383
-        }
384
-    }
385
-
386
-    /**
387
-     * Use the list of locked packages to constrain the loaded packages
388
-     * This will reduce packages with significant numbers of historical versions to a smaller number
389
-     * and reduce the resulting rule set that is generated
390
-     *
391
-     * @return void
392
-     */
393
-    private function optimizeImpossiblePackagesAway(Request $request, Pool $pool)
394
-    {
395
-        if (count($request->getLockedPackages()) === 0) {
396
-            return;
397
-        }
398
-
399
-        $packageIndex = array();
400
-
401
-        foreach ($pool->getPackages() as $package) {
402
-            $id = $package->id;
403
-
404
-            // Do not remove irremovable packages
405
-            if (isset($this->irremovablePackages[$id])) {
406
-                continue;
407
-            }
408
-            // Do not remove a package aliased by another package, nor aliases
409
-            if (isset($this->aliasesPerPackage[$id]) || $package instanceof AliasPackage) {
410
-                continue;
411
-            }
412
-            // Do not remove locked packages
413
-            if ($request->isFixedPackage($package) || $request->isLockedPackage($package)) {
414
-                continue;
415
-            }
416
-
417
-            $packageIndex[$package->getName()][$package->id] = $package;
418
-        }
419
-
420
-        foreach ($request->getLockedPackages() as $package) {
421
-            // If this locked package is no longer required by root or anything in the pool, it may get uninstalled so do not apply its requirements
422
-            // In a case where a requirement WERE to appear in the pool by a package that would not be used, it would've been unlocked and so not filtered still
423
-            $isUnusedPackage = true;
424
-            foreach ($package->getNames(false) as $packageName) {
425
-                if (isset($this->requireConstraintsPerPackage[$packageName])) {
426
-                    $isUnusedPackage = false;
427
-                    break;
428
-                }
429
-            }
430
-
431
-            if ($isUnusedPackage) {
432
-                continue;
433
-            }
434
-
435
-            foreach ($package->getRequires() as $link) {
436
-                $require = $link->getTarget();
437
-                if (!isset($packageIndex[$require])) {
438
-                    continue;
439
-                }
440
-
441
-                $linkConstraint = $link->getConstraint();
442
-                foreach ($packageIndex[$require] as $id => $requiredPkg) {
443
-                    if (false === CompilingMatcher::match($linkConstraint, Constraint::OP_EQ, $requiredPkg->getVersion())) {
444
-                        $this->markPackageForRemoval($id);
445
-                        unset($packageIndex[$require][$id]);
446
-                    }
447
-                }
448
-            }
449
-        }
450
-    }
31
+	/**
32
+	 * @var PolicyInterface
33
+	 */
34
+	private $policy;
35
+
36
+	/**
37
+	 * @var array<int, true>
38
+	 */
39
+	private $irremovablePackages = array();
40
+
41
+	/**
42
+	 * @var array<string, array<string, ConstraintInterface>>
43
+	 */
44
+	private $requireConstraintsPerPackage = array();
45
+
46
+	/**
47
+	 * @var array<string, array<string, ConstraintInterface>>
48
+	 */
49
+	private $conflictConstraintsPerPackage = array();
50
+
51
+	/**
52
+	 * @var array<int, true>
53
+	 */
54
+	private $packagesToRemove = array();
55
+
56
+	/**
57
+	 * @var array<int, BasePackage[]>
58
+	 */
59
+	private $aliasesPerPackage = array();
60
+
61
+	/**
62
+	 * @var array<string, array<string, string>>
63
+	 */
64
+	private $removedVersionsByPackage = array();
65
+
66
+	public function __construct(PolicyInterface $policy)
67
+	{
68
+		$this->policy = $policy;
69
+	}
70
+
71
+	/**
72
+	 * @return Pool
73
+	 */
74
+	public function optimize(Request $request, Pool $pool)
75
+	{
76
+		$this->prepare($request, $pool);
77
+
78
+		$this->optimizeByIdenticalDependencies($request, $pool);
79
+
80
+		$this->optimizeImpossiblePackagesAway($request, $pool);
81
+
82
+		$optimizedPool = $this->applyRemovalsToPool($pool);
83
+
84
+		// No need to run this recursively at the moment
85
+		// because the current optimizations cannot provide
86
+		// even more gains when ran again. Might change
87
+		// in the future with additional optimizations.
88
+
89
+		$this->irremovablePackages = array();
90
+		$this->requireConstraintsPerPackage = array();
91
+		$this->conflictConstraintsPerPackage = array();
92
+		$this->packagesToRemove = array();
93
+		$this->aliasesPerPackage = array();
94
+		$this->removedVersionsByPackage = array();
95
+
96
+		return $optimizedPool;
97
+	}
98
+
99
+	/**
100
+	 * @return void
101
+	 */
102
+	private function prepare(Request $request, Pool $pool)
103
+	{
104
+		$irremovablePackageConstraintGroups = array();
105
+
106
+		// Mark fixed or locked packages as irremovable
107
+		foreach ($request->getFixedOrLockedPackages() as $package) {
108
+			$irremovablePackageConstraintGroups[$package->getName()][] = new Constraint('==', $package->getVersion());
109
+		}
110
+
111
+		// Extract requested package requirements
112
+		foreach ($request->getRequires() as $require => $constraint) {
113
+			$constraint = Intervals::compactConstraint($constraint);
114
+			$this->requireConstraintsPerPackage[$require][(string) $constraint] = $constraint;
115
+		}
116
+
117
+		// First pass over all packages to extract information and mark package constraints irremovable
118
+		foreach ($pool->getPackages() as $package) {
119
+			// Extract package requirements
120
+			foreach ($package->getRequires() as $link) {
121
+				$constraint = Intervals::compactConstraint($link->getConstraint());
122
+				$this->requireConstraintsPerPackage[$link->getTarget()][(string) $constraint] = $constraint;
123
+			}
124
+			// Extract package conflicts
125
+			foreach ($package->getConflicts() as $link) {
126
+				$constraint = Intervals::compactConstraint($link->getConstraint());
127
+				$this->conflictConstraintsPerPackage[$link->getTarget()][(string) $constraint] = $constraint;
128
+			}
129
+
130
+			// Keep track of alias packages for every package so if either the alias or aliased is kept
131
+			// we keep the others as they are a unit of packages really
132
+			if ($package instanceof AliasPackage) {
133
+				$this->aliasesPerPackage[$package->getAliasOf()->id][] = $package;
134
+			}
135
+		}
136
+
137
+		$irremovablePackageConstraints = array();
138
+		foreach ($irremovablePackageConstraintGroups as $packageName => $constraints) {
139
+			$irremovablePackageConstraints[$packageName] = 1 === \count($constraints) ? $constraints[0] : new MultiConstraint($constraints, false);
140
+		}
141
+		unset($irremovablePackageConstraintGroups);
142
+
143
+		// Mark the packages as irremovable based on the constraints
144
+		foreach ($pool->getPackages() as $package) {
145
+			if (!isset($irremovablePackageConstraints[$package->getName()])) {
146
+				continue;
147
+			}
148
+
149
+			if (CompilingMatcher::match($irremovablePackageConstraints[$package->getName()], Constraint::OP_EQ, $package->getVersion())) {
150
+				$this->markPackageIrremovable($package);
151
+			}
152
+		}
153
+	}
154
+
155
+	/**
156
+	 * @return void
157
+	 */
158
+	private function markPackageIrremovable(BasePackage $package)
159
+	{
160
+		$this->irremovablePackages[$package->id] = true;
161
+		if ($package instanceof AliasPackage) {
162
+			// recursing here so aliasesPerPackage for the aliasOf can be checked
163
+			// and all its aliases marked as irremovable as well
164
+			$this->markPackageIrremovable($package->getAliasOf());
165
+		}
166
+		if (isset($this->aliasesPerPackage[$package->id])) {
167
+			foreach ($this->aliasesPerPackage[$package->id] as $aliasPackage) {
168
+				$this->irremovablePackages[$aliasPackage->id] = true;
169
+			}
170
+		}
171
+	}
172
+
173
+	/**
174
+	 * @return Pool Optimized pool
175
+	 */
176
+	private function applyRemovalsToPool(Pool $pool)
177
+	{
178
+		$packages = array();
179
+		$removedVersions = array();
180
+		foreach ($pool->getPackages() as $package) {
181
+			if (!isset($this->packagesToRemove[$package->id])) {
182
+				$packages[] = $package;
183
+			} else {
184
+				$removedVersions[$package->getName()][$package->getVersion()] = $package->getPrettyVersion();
185
+			}
186
+		}
187
+
188
+		$optimizedPool = new Pool($packages, $pool->getUnacceptableFixedOrLockedPackages(), $removedVersions, $this->removedVersionsByPackage);
189
+
190
+		return $optimizedPool;
191
+	}
192
+
193
+	/**
194
+	 * @return void
195
+	 */
196
+	private function optimizeByIdenticalDependencies(Request $request, Pool $pool)
197
+	{
198
+		$identicalDefinitionsPerPackage = array();
199
+		$packageIdenticalDefinitionLookup = array();
200
+
201
+		foreach ($pool->getPackages() as $package) {
202
+
203
+			// If that package was already marked irremovable, we can skip
204
+			// the entire process for it
205
+			if (isset($this->irremovablePackages[$package->id])) {
206
+				continue;
207
+			}
208
+
209
+			$this->markPackageForRemoval($package->id);
210
+
211
+			$dependencyHash = $this->calculateDependencyHash($package);
212
+
213
+			foreach ($package->getNames(false) as $packageName) {
214
+
215
+				if (!isset($this->requireConstraintsPerPackage[$packageName])) {
216
+					continue;
217
+				}
218
+
219
+				foreach ($this->requireConstraintsPerPackage[$packageName] as $requireConstraint) {
220
+					$groupHashParts = array();
221
+
222
+					if (CompilingMatcher::match($requireConstraint, Constraint::OP_EQ, $package->getVersion())) {
223
+						$groupHashParts[] = 'require:' . (string) $requireConstraint;
224
+					}
225
+
226
+					if ($package->getReplaces()) {
227
+						foreach ($package->getReplaces() as $link) {
228
+							if (CompilingMatcher::match($link->getConstraint(), Constraint::OP_EQ, $package->getVersion())) {
229
+								// Use the same hash part as the regular require hash because that's what the replacement does
230
+								$groupHashParts[] = 'require:' . (string) $link->getConstraint();
231
+							}
232
+						}
233
+					}
234
+
235
+					if (isset($this->conflictConstraintsPerPackage[$packageName])) {
236
+						foreach ($this->conflictConstraintsPerPackage[$packageName] as $conflictConstraint) {
237
+							if (CompilingMatcher::match($conflictConstraint, Constraint::OP_EQ, $package->getVersion())) {
238
+								$groupHashParts[] = 'conflict:' . (string) $conflictConstraint;
239
+							}
240
+						}
241
+					}
242
+
243
+					if (!$groupHashParts) {
244
+						continue;
245
+					}
246
+
247
+					$groupHash = implode('', $groupHashParts);
248
+					$identicalDefinitionsPerPackage[$packageName][$groupHash][$dependencyHash][] = $package;
249
+					$packageIdenticalDefinitionLookup[$package->id][$packageName] = array('groupHash' => $groupHash, 'dependencyHash' => $dependencyHash);
250
+				}
251
+			}
252
+		}
253
+
254
+		foreach ($identicalDefinitionsPerPackage as $constraintGroups) {
255
+			foreach ($constraintGroups as $constraintGroup) {
256
+				foreach ($constraintGroup as $packages) {
257
+					// Only one package in this constraint group has the same requirements, we're not allowed to remove that package
258
+					if (1 === \count($packages)) {
259
+						$this->keepPackage($packages[0], $identicalDefinitionsPerPackage, $packageIdenticalDefinitionLookup);
260
+						continue;
261
+					}
262
+
263
+					// Otherwise we find out which one is the preferred package in this constraint group which is
264
+					// then not allowed to be removed either
265
+					$literals = array();
266
+
267
+					foreach ($packages as $package) {
268
+						$literals[] = $package->id;
269
+					}
270
+
271
+					foreach ($this->policy->selectPreferredPackages($pool, $literals) as $preferredLiteral) {
272
+						$this->keepPackage($pool->literalToPackage($preferredLiteral), $identicalDefinitionsPerPackage, $packageIdenticalDefinitionLookup);
273
+					}
274
+				}
275
+			}
276
+		}
277
+	}
278
+
279
+	/**
280
+	 * @return string
281
+	 */
282
+	private function calculateDependencyHash(BasePackage $package)
283
+	{
284
+		$hash = '';
285
+
286
+		$hashRelevantLinks = array(
287
+			'requires' => $package->getRequires(),
288
+			'conflicts' => $package->getConflicts(),
289
+			'replaces' => $package->getReplaces(),
290
+			'provides' => $package->getProvides()
291
+		);
292
+
293
+		foreach ($hashRelevantLinks as $key => $links) {
294
+			if (0 === \count($links)) {
295
+				continue;
296
+			}
297
+
298
+			// start new hash section
299
+			$hash .= $key . ':';
300
+
301
+			$subhash = array();
302
+
303
+			foreach ($links as $link) {
304
+				// To get the best dependency hash matches we should use Intervals::compactConstraint() here.
305
+				// However, the majority of projects are going to specify their constraints already pretty
306
+				// much in the best variant possible. In other words, we'd be wasting time here and it would actually hurt
307
+				// performance more than the additional few packages that could be filtered out would benefit the process.
308
+				$subhash[$link->getTarget()] = (string) $link->getConstraint();
309
+			}
310
+
311
+			// Sort for best result
312
+			ksort($subhash);
313
+
314
+			foreach ($subhash as $target => $constraint) {
315
+				$hash .= $target . '@' . $constraint;
316
+			}
317
+		}
318
+
319
+		return $hash;
320
+	}
321
+
322
+	/**
323
+	 * @param int $id
324
+	 * @return void
325
+	 */
326
+	private function markPackageForRemoval($id)
327
+	{
328
+		// We are not allowed to remove packages if they have been marked as irremovable
329
+		if (isset($this->irremovablePackages[$id])) {
330
+			throw new \LogicException('Attempted removing a package which was previously marked irremovable');
331
+		}
332
+
333
+		$this->packagesToRemove[$id] = true;
334
+	}
335
+
336
+	/**
337
+	 * @param array<string, array<string, array<string, list<BasePackage>>>> $identicalDefinitionsPerPackage
338
+	 * @param array<int, array<string, array{groupHash: string, dependencyHash: string}>> $packageIdenticalDefinitionLookup
339
+	 * @return void
340
+	 */
341
+	private function keepPackage(BasePackage $package, $identicalDefinitionsPerPackage, $packageIdenticalDefinitionLookup)
342
+	{
343
+		unset($this->packagesToRemove[$package->id]);
344
+
345
+		if ($package instanceof AliasPackage) {
346
+			// recursing here so aliasesPerPackage for the aliasOf can be checked
347
+			// and all its aliases marked to be kept as well
348
+			$this->keepPackage($package->getAliasOf(), $identicalDefinitionsPerPackage, $packageIdenticalDefinitionLookup);
349
+		}
350
+
351
+		// record all the versions of the package group so we can list them later in Problem output
352
+		foreach ($package->getNames(false) as $name) {
353
+			if (isset($packageIdenticalDefinitionLookup[$package->id][$name])) {
354
+				$packageGroupPointers = $packageIdenticalDefinitionLookup[$package->id][$name];
355
+				$packageGroup = $identicalDefinitionsPerPackage[$name][$packageGroupPointers['groupHash']][$packageGroupPointers['dependencyHash']];
356
+				foreach ($packageGroup as $pkg) {
357
+					if ($pkg instanceof AliasPackage && $pkg->getPrettyVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) {
358
+						$pkg = $pkg->getAliasOf();
359
+					}
360
+					$this->removedVersionsByPackage[spl_object_hash($package)][$pkg->getVersion()] = $pkg->getPrettyVersion();
361
+				}
362
+			}
363
+		}
364
+
365
+		if (isset($this->aliasesPerPackage[$package->id])) {
366
+			foreach ($this->aliasesPerPackage[$package->id] as $aliasPackage) {
367
+				unset($this->packagesToRemove[$aliasPackage->id]);
368
+
369
+				// record all the versions of the package group so we can list them later in Problem output
370
+				foreach ($aliasPackage->getNames(false) as $name) {
371
+					if (isset($packageIdenticalDefinitionLookup[$aliasPackage->id][$name])) {
372
+						$packageGroupPointers = $packageIdenticalDefinitionLookup[$aliasPackage->id][$name];
373
+						$packageGroup = $identicalDefinitionsPerPackage[$name][$packageGroupPointers['groupHash']][$packageGroupPointers['dependencyHash']];
374
+						foreach ($packageGroup as $pkg) {
375
+							if ($pkg instanceof AliasPackage && $pkg->getPrettyVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) {
376
+								$pkg = $pkg->getAliasOf();
377
+							}
378
+							$this->removedVersionsByPackage[spl_object_hash($aliasPackage)][$pkg->getVersion()] = $pkg->getPrettyVersion();
379
+						}
380
+					}
381
+				}
382
+			}
383
+		}
384
+	}
385
+
386
+	/**
387
+	 * Use the list of locked packages to constrain the loaded packages
388
+	 * This will reduce packages with significant numbers of historical versions to a smaller number
389
+	 * and reduce the resulting rule set that is generated
390
+	 *
391
+	 * @return void
392
+	 */
393
+	private function optimizeImpossiblePackagesAway(Request $request, Pool $pool)
394
+	{
395
+		if (count($request->getLockedPackages()) === 0) {
396
+			return;
397
+		}
398
+
399
+		$packageIndex = array();
400
+
401
+		foreach ($pool->getPackages() as $package) {
402
+			$id = $package->id;
403
+
404
+			// Do not remove irremovable packages
405
+			if (isset($this->irremovablePackages[$id])) {
406
+				continue;
407
+			}
408
+			// Do not remove a package aliased by another package, nor aliases
409
+			if (isset($this->aliasesPerPackage[$id]) || $package instanceof AliasPackage) {
410
+				continue;
411
+			}
412
+			// Do not remove locked packages
413
+			if ($request->isFixedPackage($package) || $request->isLockedPackage($package)) {
414
+				continue;
415
+			}
416
+
417
+			$packageIndex[$package->getName()][$package->id] = $package;
418
+		}
419
+
420
+		foreach ($request->getLockedPackages() as $package) {
421
+			// If this locked package is no longer required by root or anything in the pool, it may get uninstalled so do not apply its requirements
422
+			// In a case where a requirement WERE to appear in the pool by a package that would not be used, it would've been unlocked and so not filtered still
423
+			$isUnusedPackage = true;
424
+			foreach ($package->getNames(false) as $packageName) {
425
+				if (isset($this->requireConstraintsPerPackage[$packageName])) {
426
+					$isUnusedPackage = false;
427
+					break;
428
+				}
429
+			}
430
+
431
+			if ($isUnusedPackage) {
432
+				continue;
433
+			}
434
+
435
+			foreach ($package->getRequires() as $link) {
436
+				$require = $link->getTarget();
437
+				if (!isset($packageIndex[$require])) {
438
+					continue;
439
+				}
440
+
441
+				$linkConstraint = $link->getConstraint();
442
+				foreach ($packageIndex[$require] as $id => $requiredPkg) {
443
+					if (false === CompilingMatcher::match($linkConstraint, Constraint::OP_EQ, $requiredPkg->getVersion())) {
444
+						$this->markPackageForRemoval($id);
445
+						unset($packageIndex[$require][$id]);
446
+					}
447
+				}
448
+			}
449
+		}
450
+	}
451 451
 }
Please login to merge, or discard this patch.
Filter/PlatformRequirementFilter/PlatformRequirementFilterInterface.php 1 patch
Indentation   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -4,9 +4,9 @@
 block discarded – undo
4 4
 
5 5
 interface PlatformRequirementFilterInterface
6 6
 {
7
-    /**
8
-     * @param string $req
9
-     * @return bool
10
-     */
11
-    public function isIgnored($req);
7
+	/**
8
+	 * @param string $req
9
+	 * @return bool
10
+	 */
11
+	public function isIgnored($req);
12 12
 }
Please login to merge, or discard this patch.
Filter/PlatformRequirementFilter/IgnoreNothingPlatformRequirementFilter.php 1 patch
Indentation   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -4,12 +4,12 @@
 block discarded – undo
4 4
 
5 5
 final class IgnoreNothingPlatformRequirementFilter implements PlatformRequirementFilterInterface
6 6
 {
7
-    /**
8
-     * @param string $req
9
-     * @return false
10
-     */
11
-    public function isIgnored($req)
12
-    {
13
-        return false;
14
-    }
7
+	/**
8
+	 * @param string $req
9
+	 * @return false
10
+	 */
11
+	public function isIgnored($req)
12
+	{
13
+		return false;
14
+	}
15 15
 }
Please login to merge, or discard this patch.
Filter/PlatformRequirementFilter/IgnoreAllPlatformRequirementFilter.php 1 patch
Indentation   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -6,12 +6,12 @@
 block discarded – undo
6 6
 
7 7
 final class IgnoreAllPlatformRequirementFilter implements PlatformRequirementFilterInterface
8 8
 {
9
-    /**
10
-     * @param string $req
11
-     * @return bool
12
-     */
13
-    public function isIgnored($req)
14
-    {
15
-        return PlatformRepository::isPlatformPackage($req);
16
-    }
9
+	/**
10
+	 * @param string $req
11
+	 * @return bool
12
+	 */
13
+	public function isIgnored($req)
14
+	{
15
+		return PlatformRepository::isPlatformPackage($req);
16
+	}
17 17
 }
Please login to merge, or discard this patch.
Filter/PlatformRequirementFilter/PlatformRequirementFilterFactory.php 1 patch
Indentation   +34 added lines, -34 removed lines patch added patch discarded remove patch
@@ -4,42 +4,42 @@
 block discarded – undo
4 4
 
5 5
 final class PlatformRequirementFilterFactory
6 6
 {
7
-    /**
8
-     * @param mixed $boolOrList
9
-     *
10
-     * @return PlatformRequirementFilterInterface
11
-     */
12
-    public static function fromBoolOrList($boolOrList)
13
-    {
14
-        if (is_bool($boolOrList)) {
15
-            return $boolOrList ? self::ignoreAll() : self::ignoreNothing();
16
-        }
7
+	/**
8
+	 * @param mixed $boolOrList
9
+	 *
10
+	 * @return PlatformRequirementFilterInterface
11
+	 */
12
+	public static function fromBoolOrList($boolOrList)
13
+	{
14
+		if (is_bool($boolOrList)) {
15
+			return $boolOrList ? self::ignoreAll() : self::ignoreNothing();
16
+		}
17 17
 
18
-        if (is_array($boolOrList)) {
19
-            return new IgnoreListPlatformRequirementFilter($boolOrList);
20
-        }
18
+		if (is_array($boolOrList)) {
19
+			return new IgnoreListPlatformRequirementFilter($boolOrList);
20
+		}
21 21
 
22
-        throw new \InvalidArgumentException(
23
-            sprintf(
24
-                'PlatformRequirementFilter: Unknown $boolOrList parameter %s. Please report at https://github.com/composer/composer/issues/new.',
25
-                gettype($boolOrList)
26
-            )
27
-        );
28
-    }
22
+		throw new \InvalidArgumentException(
23
+			sprintf(
24
+				'PlatformRequirementFilter: Unknown $boolOrList parameter %s. Please report at https://github.com/composer/composer/issues/new.',
25
+				gettype($boolOrList)
26
+			)
27
+		);
28
+	}
29 29
 
30
-    /**
31
-     * @return PlatformRequirementFilterInterface
32
-     */
33
-    public static function ignoreAll()
34
-    {
35
-        return new IgnoreAllPlatformRequirementFilter();
36
-    }
30
+	/**
31
+	 * @return PlatformRequirementFilterInterface
32
+	 */
33
+	public static function ignoreAll()
34
+	{
35
+		return new IgnoreAllPlatformRequirementFilter();
36
+	}
37 37
 
38
-    /**
39
-     * @return PlatformRequirementFilterInterface
40
-     */
41
-    public static function ignoreNothing()
42
-    {
43
-        return new IgnoreNothingPlatformRequirementFilter();
44
-    }
38
+	/**
39
+	 * @return PlatformRequirementFilterInterface
40
+	 */
41
+	public static function ignoreNothing()
42
+	{
43
+		return new IgnoreNothingPlatformRequirementFilter();
44
+	}
45 45
 }
Please login to merge, or discard this patch.
Filter/PlatformRequirementFilter/IgnoreListPlatformRequirementFilter.php 1 patch
Indentation   +57 added lines, -57 removed lines patch added patch discarded remove patch
@@ -14,70 +14,70 @@
 block discarded – undo
14 14
 
15 15
 final class IgnoreListPlatformRequirementFilter implements PlatformRequirementFilterInterface
16 16
 {
17
-    /**
18
-     * @var string
19
-     */
20
-    private $ignoreRegex;
17
+	/**
18
+	 * @var string
19
+	 */
20
+	private $ignoreRegex;
21 21
 
22
-    /**
23
-     * @var string
24
-     */
25
-    private $ignoreUpperBoundRegex;
22
+	/**
23
+	 * @var string
24
+	 */
25
+	private $ignoreUpperBoundRegex;
26 26
 
27
-    /**
28
-     * @param string[] $reqList
29
-     */
30
-    public function __construct(array $reqList)
31
-    {
32
-        $ignoreAll = $ignoreUpperBound = array();
33
-        foreach ($reqList as $req) {
34
-            if (substr($req, -1) === '+') {
35
-                $ignoreUpperBound[] = substr($req, 0, -1);
36
-            } else {
37
-                $ignoreAll[] = $req;
38
-            }
39
-        }
40
-        $this->ignoreRegex = BasePackage::packageNamesToRegexp($ignoreAll);
41
-        $this->ignoreUpperBoundRegex = BasePackage::packageNamesToRegexp($ignoreUpperBound);
42
-    }
27
+	/**
28
+	 * @param string[] $reqList
29
+	 */
30
+	public function __construct(array $reqList)
31
+	{
32
+		$ignoreAll = $ignoreUpperBound = array();
33
+		foreach ($reqList as $req) {
34
+			if (substr($req, -1) === '+') {
35
+				$ignoreUpperBound[] = substr($req, 0, -1);
36
+			} else {
37
+				$ignoreAll[] = $req;
38
+			}
39
+		}
40
+		$this->ignoreRegex = BasePackage::packageNamesToRegexp($ignoreAll);
41
+		$this->ignoreUpperBoundRegex = BasePackage::packageNamesToRegexp($ignoreUpperBound);
42
+	}
43 43
 
44
-    /**
45
-     * @param string $req
46
-     * @return bool
47
-     */
48
-    public function isIgnored($req)
49
-    {
50
-        if (!PlatformRepository::isPlatformPackage($req)) {
51
-            return false;
52
-        }
44
+	/**
45
+	 * @param string $req
46
+	 * @return bool
47
+	 */
48
+	public function isIgnored($req)
49
+	{
50
+		if (!PlatformRepository::isPlatformPackage($req)) {
51
+			return false;
52
+		}
53 53
 
54
-        return Preg::isMatch($this->ignoreRegex, $req);
55
-    }
54
+		return Preg::isMatch($this->ignoreRegex, $req);
55
+	}
56 56
 
57
-    /**
58
-     * @param string $req
59
-     * @return ConstraintInterface
60
-     */
61
-    public function filterConstraint($req, ConstraintInterface $constraint)
62
-    {
63
-        if (!PlatformRepository::isPlatformPackage($req)) {
64
-            return $constraint;
65
-        }
57
+	/**
58
+	 * @param string $req
59
+	 * @return ConstraintInterface
60
+	 */
61
+	public function filterConstraint($req, ConstraintInterface $constraint)
62
+	{
63
+		if (!PlatformRepository::isPlatformPackage($req)) {
64
+			return $constraint;
65
+		}
66 66
 
67
-        if (!Preg::isMatch($this->ignoreUpperBoundRegex, $req)) {
68
-            return $constraint;
69
-        }
67
+		if (!Preg::isMatch($this->ignoreUpperBoundRegex, $req)) {
68
+			return $constraint;
69
+		}
70 70
 
71
-        if (Preg::isMatch($this->ignoreRegex, $req)) {
72
-            return new MatchAllConstraint;
73
-        }
71
+		if (Preg::isMatch($this->ignoreRegex, $req)) {
72
+			return new MatchAllConstraint;
73
+		}
74 74
 
75
-        $intervals = Intervals::get($constraint);
76
-        $last = end($intervals['numeric']);
77
-        if ($last !== false && (string) $last->getEnd() !== (string) Interval::untilPositiveInfinity()) {
78
-            $constraint = new MultiConstraint(array($constraint, new Constraint('>=', $last->getEnd()->getVersion())), false);
79
-        }
75
+		$intervals = Intervals::get($constraint);
76
+		$last = end($intervals['numeric']);
77
+		if ($last !== false && (string) $last->getEnd() !== (string) Interval::untilPositiveInfinity()) {
78
+			$constraint = new MultiConstraint(array($constraint, new Constraint('>=', $last->getEnd()->getVersion())), false);
79
+		}
80 80
 
81
-        return $constraint;
82
-    }
81
+		return $constraint;
82
+	}
83 83
 }
Please login to merge, or discard this patch.