/** * Conflicts checker/solver. * When $amSolvedValues is null, it will only check for dependancies problems and throw exceptions. * When $amSolvedValues is not null, it must be an array of misc values, at the same indexes than $aoComponents. * If a solution is found, $amSolvedValues will be reorganized in the correct order. */ private function doCheckOrSolveDependancies($aoComponents, $amSolvedValues = null, $nDepth = 0) { self::debug("solveDependancies() for " . $this->getSourceComponent()->getComponentName()); // search for source/target indices... $nSourceComponentIndice = null; $nTargetComponentIndice = null; foreach ($aoComponents as $i => $oComponent) { if ($nSourceComponentIndice === null && $this->sourceComponentMatches($oComponent)) { $nSourceComponentIndice = $i; } else { if ($nTargetComponentIndice === null && $this->targetComponentMatches($oComponent)) { $nTargetComponentIndice = $i; } } if ($nSourceComponentIndice !== null && $nTargetComponentIndice !== null) { break; } } if ($nSourceComponentIndice === null) { throw new AnwUnexpectedException("Source component not found"); //should never happend } // begin dependancies resolution if ($nTargetComponentIndice !== null) { //the conflicting component has been found... if ($this->mSolution == self::SOLUTION_NONE) { // there is no solution self::debug("conflict between " . $this->getSourceComponent()->getComponentName() . " and " . $this->getTargetComponentName() . " : no solution"); throw new AnwDependancyException(AnwComponent::g_editcontent("dependancy_conflict", array('component1' => $this->getSourceComponent()->getComponentName(), 'component2' => $this->getTargetComponentName()))); } else { // there is a solution, we will try to apply it... $bSolvedValuesWereChanged = false; if ($this->mSolution == self::SOLUTION_LOAD_BEFORE && $nSourceComponentIndice < $nTargetComponentIndice || $this->mSolution == self::SOLUTION_LOAD_AFTER && $nSourceComponentIndice > $nTargetComponentIndice) { // already solved self::debug("conflict between " . $this->getSourceComponent()->getComponentName() . " and " . $this->getTargetComponentName() . " : already solved"); } else { self::debug("conflict between " . $this->getSourceComponent()->getComponentName() . " and " . $this->getTargetComponentName() . " : solvable"); if ($amSolvedValues !== null) { // conflict can be solved by permuting the two components (must permute it in $aoComponents AND $amSolvedValues) list($aoComponents, $amSolvedValues) = AnwUtils::permuteMultipleArrays(array($aoComponents, $amSolvedValues), $nSourceComponentIndice, $nTargetComponentIndice); $bSolvedValuesWereChanged = true; } else { throw new AnwDependancyException(AnwComponent::g_editcontent("dependancy_conflict_unsolved", array('component1' => $this->getSourceComponent()->getComponentName(), 'component2' => $this->getTargetComponentName()))); } } if ($amSolvedValues !== null && $bSolvedValuesWereChanged) { // we have to check again the whole values, to be sure that we didn't break a dependancy while reorganizing $amSolvedValues $nDepth++; if ($nDepth > 3) { // we may be in an infinite dependancies problem... give up! self::debug("amSolvedValues have changed, but nDepth exceeded"); throw new AnwDependancyException(AnwComponent::g_editcontent("dependancy_conflict_exceed", array('component1' => $this->getSourceComponent()->getComponentName(), 'component2' => $this->getTargetComponentName()))); } else { self::debug("amSolvedValues have changed, checking again whole values"); $aoComponents = $this->doCheckOrSolveDependancies($aoComponents, $amSolvedValues, $nDepth); //recursive call } } } } else { //no dependancy problem self::debug("conflict between " . $this->getSourceComponent()->getComponentName() . " and " . $this->getTargetComponentName() . " : no dependancy problem"); } return $amSolvedValues; }