diff --git a/src/Constraint/MultiConstraint.php b/src/Constraint/MultiConstraint.php index 31e2c45c..39d643f7 100644 --- a/src/Constraint/MultiConstraint.php +++ b/src/Constraint/MultiConstraint.php @@ -237,8 +237,6 @@ private static function optimizeConstraints(array $constraints, $conjunctive) && $left->conjunctive && $right instanceof self && $right->conjunctive - && \count($left->constraints) === 2 - && \count($right->constraints) === 2 && ($left0 = (string) $left->constraints[0]) && $left0[0] === '>' && $left0[1] === '=' && ($left1 = (string) $left->constraints[1]) @@ -249,6 +247,29 @@ private static function optimizeConstraints(array $constraints, $conjunctive) && $right1[0] === '<' && substr($left1, 2) === substr($right0, 3) ) { + for ($j = 2, $m = count($right->constraints); $j < $m; $j++) { + $c = (string)$right->constraints[$j]; + switch ($c[0]) { + case '!': + case '<': + case '=': + break; + default: + continue 3; + } + } + for ($j = 2, $m = count($left->constraints); $j < $m; $j++) { + $c = (string)$left->constraints[$j]; + switch ($c[0]) { + case '!': + case '>': + case '=': + break; + default: + continue 3; + } + } + $optimized = true; $left = new MultiConstraint( array_merge( @@ -260,10 +281,11 @@ private static function optimizeConstraints(array $constraints, $conjunctive) \array_slice($right->constraints, 2) ), true); - } else { - $mergedConstraints[] = $left; - $left = $right; + continue; } + + $mergedConstraints[] = $left; + $left = $right; } if ($optimized) { $mergedConstraints[] = $left; diff --git a/tests/Constraint/MultiConstraintTest.php b/tests/Constraint/MultiConstraintTest.php index fcc83ed9..2d559633 100644 --- a/tests/Constraint/MultiConstraintTest.php +++ b/tests/Constraint/MultiConstraintTest.php @@ -312,7 +312,7 @@ public function multiConstraintOptimizations() true // conjunctive ), ), - 'Test does not collapse when one side is more complex' => array( + 'Test does not collapse when one side changes the bounds' => array( '~2.5.9 || ~2.6, >=2.6.2', new MultiConstraint( array( @@ -335,96 +335,39 @@ public function multiConstraintOptimizations() false ) ), - 'Test does not collapse multiple contiguous with other constraint but collapses the end' => array( + 'Test collapses multiple contiguous with other constraint' => array( '^1.0 || ^2.0 !=2.0.1 || ^3.0 || ^4.0', new MultiConstraint( array( - new MultiConstraint( - array( - new Constraint('>=', '1.0.0.0-dev'), - new Constraint('<', '2.0.0.0-dev'), - ), - true // conjunctive - ), - new MultiConstraint( - array( - new Constraint('>=', '2.0.0.0-dev'), - new Constraint('<', '3.0.0.0-dev'), - new Constraint('!=', '2.0.1.0'), - ), - true // conjunctive - ), - new MultiConstraint( - array( - new Constraint('>=', '3.0.0.0-dev'), - new Constraint('<', '5.0.0.0-dev'), - ), - true // conjunctive - ), + new Constraint('>=', '1.0.0.0-dev'), + new Constraint('<', '5.0.0.0-dev'), + new Constraint('!=', '2.0.1.0'), ), - false + true ) ), - 'Test does not collapse multiple contiguous with multiple other constraint' => array( + 'Test collapses multiple contiguous with multiple other constraint' => array( '^1.0 != 1.0.1 || ^2.0 !=2.0.1 || ^3.0 || ^4.0 != 4.0.1', new MultiConstraint( array( - new MultiConstraint( - array( - new Constraint('>=', '1.0.0.0-dev'), - new Constraint('<', '2.0.0.0-dev'), - new Constraint('!=', '1.0.1.0'), - ), - true // conjunctive - ), - new MultiConstraint( - array( - new Constraint('>=', '2.0.0.0-dev'), - new Constraint('<', '3.0.0.0-dev'), - new Constraint('!=', '2.0.1.0'), - ), - true // conjunctive - ), - new MultiConstraint( - array( - new Constraint('>=', '3.0.0.0-dev'), - new Constraint('<', '4.0.0.0-dev'), - ), - true // conjunctive - ), - new MultiConstraint( - array( - new Constraint('>=', '4.0.0.0-dev'), - new Constraint('<', '5.0.0.0-dev'), - new Constraint('!=', '4.0.1.0'), - ), - true // conjunctive - ), + new Constraint('>=', '1.0.0.0-dev'), + new Constraint('<', '5.0.0.0-dev'), + new Constraint('!=', '1.0.1.0'), + new Constraint('!=', '2.0.1.0'), + new Constraint('!=', '4.0.1.0'), ), - false + true ) ), - 'Test does not collapse if contiguous range and other constraints also apply' => array( + 'Test collapse if contiguous range and other constraints also apply' => array( '~0.1 || ~1.0 !=1.0.1', new MultiConstraint( array( - new MultiConstraint( - array( - new Constraint('>=', '0.1.0.0-dev'), - new Constraint('<', '1.0.0.0-dev'), - ), - true // conjunctive - ), - new MultiConstraint( - array( - new Constraint('>=', '1.0.0.0-dev'), - new Constraint('<', '2.0.0.0-dev'), - new Constraint('!=', '1.0.1.0'), - ), - true // conjunctive - ), + new Constraint('>=', '0.1.0.0-dev'), + new Constraint('<', '2.0.0.0-dev'), + new Constraint('!=', '1.0.1.0'), ), - false + true // conjunctive ) ), 'Parse caret constraints must not collapse if non contiguous range' => array(