This repository has been archived by the owner on Feb 6, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 89
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'hotfix/89' into develop
Forward port #89
- Loading branch information
Showing
6 changed files
with
340 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
<?php | ||
/** | ||
* Zend Framework (http://framework.zend.com/) | ||
* | ||
* @link http://github.com/zendframework/zf2 for the canonical source repository | ||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) | ||
* @license http://framework.zend.com/license/new-bsd New BSD License | ||
*/ | ||
|
||
namespace Zend\ServiceManager\Exception; | ||
|
||
class CyclicAliasException extends InvalidArgumentException | ||
{ | ||
/** | ||
* @param string[] $aliases map of referenced services, indexed by alias name (string) | ||
* | ||
* @return self | ||
*/ | ||
public static function fromAliasesMap(array $aliases) | ||
{ | ||
$detectedCycles = array_filter(array_map( | ||
function ($alias) use ($aliases) { | ||
return self::getCycleFor($aliases, $alias); | ||
}, | ||
array_keys($aliases) | ||
)); | ||
|
||
if (! $detectedCycles) { | ||
return new self(sprintf( | ||
"A cycle was detected within the following aliases map:\n\n%s", | ||
self::printReferencesMap($aliases) | ||
)); | ||
} | ||
|
||
return new self(sprintf( | ||
"Cycles were detected within the provided aliases:\n\n%s\n\n" | ||
. "The cycle was detected in the following alias map:\n\n%s", | ||
self::printCycles(self::deDuplicateDetectedCycles($detectedCycles)), | ||
self::printReferencesMap($aliases) | ||
)); | ||
} | ||
|
||
/** | ||
* Retrieves the cycle detected for the given $alias, or `null` if no cycle was detected | ||
* | ||
* @param string[] $aliases | ||
* @param string $alias | ||
* | ||
* @return array|null | ||
*/ | ||
private static function getCycleFor(array $aliases, $alias) | ||
{ | ||
$cycleCandidate = []; | ||
$targetName = $alias; | ||
|
||
while (isset($aliases[$targetName])) { | ||
if (isset($cycleCandidate[$targetName])) { | ||
return $cycleCandidate; | ||
} | ||
|
||
$cycleCandidate[$targetName] = true; | ||
|
||
$targetName = $aliases[$targetName]; | ||
} | ||
|
||
return null; | ||
} | ||
|
||
/** | ||
* @param string[] $aliases | ||
* | ||
* @return string | ||
*/ | ||
private static function printReferencesMap(array $aliases) | ||
{ | ||
$map = []; | ||
|
||
foreach ($aliases as $alias => $reference) { | ||
$map[] = '"' . $alias . '" => "' . $reference . '"'; | ||
} | ||
|
||
return "[\n" . implode("\n", $map) . "\n]"; | ||
} | ||
|
||
/** | ||
* @param string[][] $detectedCycles | ||
* | ||
* @return string | ||
*/ | ||
private static function printCycles(array $detectedCycles) | ||
{ | ||
return "[\n" . implode("\n", array_map([__CLASS__, 'printCycle'], $detectedCycles)) . "\n]"; | ||
} | ||
|
||
/** | ||
* @param string[] $detectedCycle | ||
* | ||
* @return string | ||
*/ | ||
private static function printCycle(array $detectedCycle) | ||
{ | ||
$fullCycle = array_keys($detectedCycle); | ||
$fullCycle[] = reset($fullCycle); | ||
|
||
return implode( | ||
' => ', | ||
array_map( | ||
function ($cycle) { | ||
return '"' . $cycle . '"'; | ||
}, | ||
$fullCycle | ||
) | ||
); | ||
} | ||
|
||
/** | ||
* @param bool[][] $detectedCycles | ||
* | ||
* @return bool[][] de-duplicated | ||
*/ | ||
private static function deDuplicateDetectedCycles(array $detectedCycles) | ||
{ | ||
$detectedCyclesByHash = []; | ||
|
||
foreach ($detectedCycles as $detectedCycle) { | ||
$cycleAliases = array_keys($detectedCycle); | ||
|
||
sort($cycleAliases); | ||
|
||
$hash = serialize(array_values($cycleAliases)); | ||
|
||
$detectedCyclesByHash[$hash] = isset($detectedCyclesByHash[$hash]) | ||
? $detectedCyclesByHash[$hash] | ||
: $detectedCycle; | ||
} | ||
|
||
return array_values($detectedCyclesByHash); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.