Skip to content

Commit

Permalink
Add compactConstraint method to optimize constraints
Browse files Browse the repository at this point in the history
  • Loading branch information
Seldaek committed May 19, 2020
1 parent 594e524 commit 05fe888
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 0 deletions.
38 changes: 38 additions & 0 deletions src/Intervals.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,44 @@ public static function haveIntersections(ConstraintInterface $a, ConstraintInter
return \count($intersectionIntervals['numeric']) > 0 || \count($intersectionIntervals['branches']) > 0;
}

public static function compactConstraint(ConstraintInterface $constraint)
{
if (!$constraint instanceof MultiConstraint) {
return $constraint;
}

$intervals = self::generateIntervals($constraint);
$constraints = array();
foreach ($intervals['numeric'] as $interval) {
if ($interval->getStart() === Interval::zero()) {
$constraints[] = $interval->getEnd();
} elseif ($interval->getEnd() === Interval::positiveInfinity()) {
$constraints[] = $interval->getStart();
} else {
$constraints[] = new MultiConstraint(array($interval->getStart(), $interval->getEnd()), true);
}
}
foreach ($intervals['branches'] as $branchConstraint) {
if ($branchConstraint === self::anyDev()) {
// TODO this needs a real AnyDevConstraint which only matches == dev-foo
continue;
}

$constraints[] = $dev;
}

if (\count($constraints) > 1) {
return new MultiConstraint($constraints, false);
}

if (\count($constraints) === 1) {
return $constraints[0];
}

// TODO verify it matches no dev-* constraint or anything, or create a new MatchNoneConstraint
return new Constraint('<', '0.0.0.0-dev');
}

/**
* Creates an array of numeric intervals and branch constraints representing a given constraint
*
Expand Down
33 changes: 33 additions & 0 deletions tests/IntervalsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,39 @@ class IntervalsTest extends TestCase
const INTERVAL_ANY_NODEV = '*';
const INTERVAL_NONE = '';

public function testCompactConstraint()
{
$parser = new VersionParser;

$original = new MultiConstraint(array(
new MultiConstraint(array( // 1.0 - 1.2 || ^1.5
new MultiConstraint(array(
new Constraint('>=', '1.0.0.0-dev'),
new Constraint('<', '1.3.0.0-dev'),
), true),
new MultiConstraint(array(
new Constraint('>=', '1.5.0.0-dev'),
new Constraint('<', '2.0.0.0-dev'),
), true),
), false),
new MultiConstraint(array( // 1.8 - 1.9 || ^1.12
new MultiConstraint(array(
new Constraint('>=', '1.8.0.0-dev'),
new Constraint('<', '1.10.0.0-dev'),
), true),
new MultiConstraint(array(
new Constraint('>=', '1.12.0.0-dev'),
new Constraint('<', '2.0.0.0-dev'),
), true),
), false),
), false);

$expected = $parser->parseConstraints('1.0 - 1.2 || ^1.5');

$new = Intervals::compactConstraint($original);
$this->assertSame((string) $expected, (string) $new);
}

/**
* @dataProvider intervalsProvider
*/
Expand Down

0 comments on commit 05fe888

Please sign in to comment.