|
7 | 7 |
|
8 | 8 | namespace Zend\ServiceManager\Exception;
|
9 | 9 |
|
10 |
| -use function array_filter; |
11 |
| -use function array_keys; |
12 |
| -use function array_map; |
13 |
| -use function array_values; |
14 |
| -use function implode; |
15 |
| -use function reset; |
16 |
| -use function serialize; |
17 |
| -use function sort; |
18 | 10 | use function sprintf;
|
19 | 11 |
|
20 | 12 | class CyclicAliasException extends InvalidArgumentException
|
21 | 13 | {
|
22 | 14 | /**
|
| 15 | + * @param string conflicting alias key |
23 | 16 | * @param string[] $aliases map of referenced services, indexed by alias name (string)
|
24 | 17 | *
|
25 | 18 | * @return self
|
26 | 19 | */
|
27 |
| - public static function fromAliasesMap(array $aliases) |
| 20 | + public static function fromCyclicAlias($alias, $aliases) |
28 | 21 | {
|
29 |
| - $detectedCycles = array_filter(array_map( |
30 |
| - function ($alias) use ($aliases) { |
31 |
| - return self::getCycleFor($aliases, $alias); |
32 |
| - }, |
33 |
| - array_keys($aliases) |
34 |
| - )); |
35 |
| - |
36 |
| - if (! $detectedCycles) { |
37 |
| - return new self(sprintf( |
38 |
| - "A cycle was detected within the following aliases map:\n\n%s", |
39 |
| - self::printReferencesMap($aliases) |
40 |
| - )); |
| 22 | + $msg = $alias; |
| 23 | + $cursor = $alias; |
| 24 | + while($aliases[$cursor] !== $alias) { |
| 25 | + $cursor = $aliases[$cursor]; |
| 26 | + $msg .= ' -> '. $cursor; |
41 | 27 | }
|
42 |
| - |
| 28 | + $msg .= ' -> ' . $alias . PHP_EOL; |
43 | 29 | return new self(sprintf(
|
44 |
| - "Cycles were detected within the provided aliases:\n\n%s\n\n" |
45 |
| - . "The cycle was detected in the following alias map:\n\n%s", |
46 |
| - self::printCycles(self::deDuplicateDetectedCycles($detectedCycles)), |
47 |
| - self::printReferencesMap($aliases) |
48 |
| - )); |
49 |
| - } |
50 |
| - |
51 |
| - /** |
52 |
| - * Retrieves the cycle detected for the given $alias, or `null` if no cycle was detected |
53 |
| - * |
54 |
| - * @param string[] $aliases |
55 |
| - * @param string $alias |
56 |
| - * |
57 |
| - * @return array|null |
58 |
| - */ |
59 |
| - private static function getCycleFor(array $aliases, $alias) |
60 |
| - { |
61 |
| - $cycleCandidate = []; |
62 |
| - $targetName = $alias; |
63 |
| - |
64 |
| - while (isset($aliases[$targetName])) { |
65 |
| - if (isset($cycleCandidate[$targetName])) { |
66 |
| - return $cycleCandidate; |
67 |
| - } |
68 |
| - |
69 |
| - $cycleCandidate[$targetName] = true; |
70 |
| - |
71 |
| - $targetName = $aliases[$targetName]; |
72 |
| - } |
73 |
| - |
74 |
| - return null; |
75 |
| - } |
76 |
| - |
77 |
| - /** |
78 |
| - * @param string[] $aliases |
79 |
| - * |
80 |
| - * @return string |
81 |
| - */ |
82 |
| - private static function printReferencesMap(array $aliases) |
83 |
| - { |
84 |
| - $map = []; |
85 |
| - |
86 |
| - foreach ($aliases as $alias => $reference) { |
87 |
| - $map[] = '"' . $alias . '" => "' . $reference . '"'; |
88 |
| - } |
89 |
| - |
90 |
| - return "[\n" . implode("\n", $map) . "\n]"; |
91 |
| - } |
92 |
| - |
93 |
| - /** |
94 |
| - * @param string[][] $detectedCycles |
95 |
| - * |
96 |
| - * @return string |
97 |
| - */ |
98 |
| - private static function printCycles(array $detectedCycles) |
99 |
| - { |
100 |
| - return "[\n" . implode("\n", array_map([__CLASS__, 'printCycle'], $detectedCycles)) . "\n]"; |
101 |
| - } |
102 |
| - |
103 |
| - /** |
104 |
| - * @param string[] $detectedCycle |
105 |
| - * |
106 |
| - * @return string |
107 |
| - */ |
108 |
| - private static function printCycle(array $detectedCycle) |
109 |
| - { |
110 |
| - $fullCycle = array_keys($detectedCycle); |
111 |
| - $fullCycle[] = reset($fullCycle); |
112 |
| - |
113 |
| - return implode( |
114 |
| - ' => ', |
115 |
| - array_map( |
116 |
| - function ($cycle) { |
117 |
| - return '"' . $cycle . '"'; |
118 |
| - }, |
119 |
| - $fullCycle |
120 |
| - ) |
121 |
| - ); |
122 |
| - } |
123 |
| - |
124 |
| - /** |
125 |
| - * @param bool[][] $detectedCycles |
126 |
| - * |
127 |
| - * @return bool[][] de-duplicated |
128 |
| - */ |
129 |
| - private static function deDuplicateDetectedCycles(array $detectedCycles) |
130 |
| - { |
131 |
| - $detectedCyclesByHash = []; |
132 |
| - |
133 |
| - foreach ($detectedCycles as $detectedCycle) { |
134 |
| - $cycleAliases = array_keys($detectedCycle); |
135 |
| - |
136 |
| - sort($cycleAliases); |
137 |
| - |
138 |
| - $hash = serialize(array_values($cycleAliases)); |
139 |
| - |
140 |
| - $detectedCyclesByHash[$hash] = isset($detectedCyclesByHash[$hash]) |
141 |
| - ? $detectedCyclesByHash[$hash] |
142 |
| - : $detectedCycle; |
143 |
| - } |
144 |
| - |
145 |
| - return array_values($detectedCyclesByHash); |
| 30 | + "A cycle was detected within the aliases defintions:\n%s", |
| 31 | + $msg |
| 32 | + )); |
146 | 33 | }
|
147 | 34 | }
|
0 commit comments