You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

96 lines
2.7 KiB
PHTML

<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\DependencyResolver;
/**
* @author Nils Adermann <naderman@naderman.de>
*/
class RuleWatchGraph
{
protected $watches = array();
/**
* Alters watch chains for a rule.
*
*/
public function insert(RuleWatchNode $node)
{
if ($node->getRule()->isAssertion()) {
return;
}
foreach (array($node->watch1, $node->watch2) as $literal) {
if (!isset($this->watches[$literal])) {
$this->watches[$literal] = new RuleWatchChain;
}
$this->watches[$literal]->unshift($node);
}
}
public function contains($literal)
{
return isset($this->watches[$literal]);
}
public function propagateLiteral($literal, $level, $skipCallback, $conflictCallback, $decideCallback)
{
if (!isset($this->watches[$literal])) {
return null;
}
$this->watches[$literal]->rewind();
while ($this->watches[$literal]->valid()) {
$node = $this->watches[$literal]->current();
$otherWatch = $node->getOtherWatch($literal);
if (!$node->getRule()->isDisabled() && !call_user_func($skipCallback, $otherWatch)) {
$ruleLiterals = $node->getRule()->getLiterals();
$alternativeLiterals = array_filter($ruleLiterals, function ($ruleLiteral) use ($literal, $otherWatch, $conflictCallback) {
return $literal !== $ruleLiteral &&
$otherWatch !== $ruleLiteral &&
!call_user_func($conflictCallback, $ruleLiteral);
});
if ($alternativeLiterals) {
reset($alternativeLiterals);
$this->moveWatch($literal, current($alternativeLiterals), $node);
continue;
}
if (call_user_func($conflictCallback, $otherWatch)) {
return $node->getRule();
}
call_user_func($decideCallback, $otherWatch, $level, $node->getRule());
}
$this->watches[$literal]->next();
}
return null;
}
protected function moveWatch($fromLiteral, $toLiteral, $node)
{
if (!isset($this->watches[$toLiteral])) {
$this->watches[$toLiteral] = new RuleWatchChain;
}
$node->moveWatch($fromLiteral, $toLiteral);
$this->watches[$fromLiteral]->remove();
$this->watches[$toLiteral]->unshift($node);
}
}