Add disjunctive multi-constraints with |, refs #643, fixes #1342

main
Jordi Boggiano 11 years ago
parent 37894f66a1
commit 0cccafbe81

@ -13,27 +13,41 @@
namespace Composer\Package\LinkConstraint; namespace Composer\Package\LinkConstraint;
/** /**
* Defines a conjunctive set of constraints on the target of a package link * Defines a conjunctive or disjunctive set of constraints on the target of a package link
* *
* @author Nils Adermann <naderman@naderman.de> * @author Nils Adermann <naderman@naderman.de>
* @author Jordi Boggiano <j.boggiano@seld.be>
*/ */
class MultiConstraint implements LinkConstraintInterface class MultiConstraint implements LinkConstraintInterface
{ {
protected $constraints; protected $constraints;
protected $prettyString; protected $prettyString;
protected $conjunctive;
/** /**
* Sets operator and version to compare a package with * Sets operator and version to compare a package with
* *
* @param array $constraints A conjunctive set of constraints * @param array $constraints A set of constraints
* @param bool $conjunctive Whether the constraints should be treated as conjunctive or disjunctive
*/ */
public function __construct(array $constraints) public function __construct(array $constraints, $conjunctive = true)
{ {
$this->constraints = $constraints; $this->constraints = $constraints;
$this->conjunctive = $conjunctive;
} }
public function matches(LinkConstraintInterface $provider) public function matches(LinkConstraintInterface $provider)
{ {
if (false === $this->conjunctive) {
foreach ($this->constraints as $constraint) {
if ($constraint->matches($provider)) {
return true;
}
}
return false;
}
foreach ($this->constraints as $constraint) { foreach ($this->constraints as $constraint) {
if (!$constraint->matches($provider)) { if (!$constraint->matches($provider)) {
return false; return false;
@ -64,6 +78,6 @@ class MultiConstraint implements LinkConstraintInterface
$constraints[] = $constraint->__toString(); $constraints[] = $constraint->__toString();
} }
return '['.implode(', ', $constraints).']'; return '['.implode($this->conjunctive ? ', ' : ' | ', $constraints).']';
} }
} }

@ -221,21 +221,33 @@ class VersionParser
$constraints = $match[1]; $constraints = $match[1];
} }
$constraints = preg_split('{\s*,\s*}', trim($constraints)); $orConstraints = preg_split('{\s*\|\s*}', trim($constraints));
$orGroups = array();
foreach ($orConstraints as $constraints) {
$andConstraints = preg_split('{\s*,\s*}', $constraints);
if (count($andConstraints) > 1) {
$constraintObjects = array();
foreach ($andConstraints as $constraint) {
$constraintObjects = array_merge($constraintObjects, $this->parseConstraint($constraint));
}
} else {
$constraintObjects = $this->parseConstraint($andConstraints[0]);
}
if (count($constraints) > 1) { if (1 === count($constraintObjects)) {
$constraintObjects = array(); $constraint = $constraintObjects[0];
foreach ($constraints as $constraint) { } else {
$constraintObjects = array_merge($constraintObjects, $this->parseConstraint($constraint)); $constraint = new MultiConstraint($constraintObjects);
} }
} else {
$constraintObjects = $this->parseConstraint($constraints[0]); $orGroups[] = $constraint;
} }
if (1 === count($constraintObjects)) { if (1 === count($orGroups)) {
$constraint = $constraintObjects[0]; $constraint = $orGroups[0];
} else { } else {
$constraint = new MultiConstraint($constraintObjects); $constraint = new MultiConstraint($orGroups, false);
} }
$constraint->setPrettyString($prettyConstraint); $constraint->setPrettyString($prettyConstraint);

@ -0,0 +1,24 @@
--TEST--
Disjunctive multi constraints work
--COMPOSER--
{
"repositories": [
{
"type": "package",
"package": [
{ "name": "foo", "version": "1.1.0" },
{ "name": "foo", "version": "1.0.0" },
{ "name": "bar", "version": "1.1.0", "require": { "foo": "1.0.*" } }
]
}
],
"require": {
"bar": "1.*",
"foo": "1.0.*|1.1.*"
}
}
--RUN--
install
--EXPECT--
Installing foo (1.0.0)
Installing bar (1.1.0)

@ -284,6 +284,17 @@ class VersionParserTest extends \PHPUnit_Framework_TestCase
$this->assertSame((string) $multi, (string) $parser->parseConstraints('>2.0,<=3.0')); $this->assertSame((string) $multi, (string) $parser->parseConstraints('>2.0,<=3.0'));
} }
public function testParseConstraintsMultiDisjunctiveHasPrioOverConjuctive()
{
$parser = new VersionParser;
$first = new VersionConstraint('>', '2.0.0.0');
$second = new VersionConstraint('<', '2.0.5.0-dev');
$third = new VersionConstraint('>', '2.0.6.0');
$multi1 = new MultiConstraint(array($first, $second));
$multi2 = new MultiConstraint(array($multi1, $third), false);
$this->assertSame((string) $multi2, (string) $parser->parseConstraints('>2.0,<2.0.5 | >2.0.6'));
}
public function testParseConstraintsMultiWithStabilities() public function testParseConstraintsMultiWithStabilities()
{ {
$parser = new VersionParser; $parser = new VersionParser;

Loading…
Cancel
Save