Skip to content

Commit a428e48

Browse files
Upgraded aliasing
Signed-off-by: Tom Wright <[email protected]>
1 parent d40f96e commit a428e48

File tree

5 files changed

+82
-24
lines changed

5 files changed

+82
-24
lines changed

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
* Improved namespace mapping algorithm
2+
* Upgraded namespace aliases to mount at any level
3+
* Enable recursive aliases
4+
* Added priority to aliases
5+
16
## v0.3.3 (2024-04-29)
27
* Fixed Veneer stubs in gitattributes
38

src/Handler.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,10 @@ public function map(
177177
*/
178178
public function alias(
179179
string $interface,
180-
string $alias
180+
string $alias,
181+
int $priority = 0
181182
): void {
182-
$this->getNamespaceMap()->addAlias($interface, $alias);
183+
$this->getNamespaceMap()->addAlias($interface, $alias, $priority);
183184
}
184185

185186

src/NamespaceList.php

+6-4
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99

1010
namespace DecodeLabs\Archetype;
1111

12-
use ArrayIterator;
1312
use Countable;
1413
use DecodeLabs\Glitch\Dumpable;
14+
use Generator;
1515
use IteratorAggregate;
1616

1717
/**
@@ -88,15 +88,17 @@ public function import(
8888
/**
8989
* Get iterator
9090
*
91-
* @return ArrayIterator<int, string>
91+
* @return Generator<int, string>
9292
*/
93-
public function getIterator(): ArrayIterator
93+
public function getIterator(): Generator
9494
{
9595
uasort($this->namespaces, function ($a, $b) {
9696
return $a <=> $b;
9797
});
9898

99-
return new ArrayIterator(array_reverse(array_keys($this->namespaces)));
99+
foreach (array_reverse($this->namespaces) as $namespace => $priority) {
100+
yield $priority => $namespace;
101+
}
100102
}
101103

102104
/**

src/NamespaceMap.php

+67-17
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class NamespaceMap
1717
protected array $namespaces = [];
1818

1919
/**
20-
* @var array<string, array<string>>
20+
* @var array<string, NamespaceList>
2121
*/
2222
protected array $aliases = [];
2323

@@ -69,16 +69,20 @@ public function remove(
6969

7070
/**
7171
* Add alias
72+
*
73+
* @return $this
7274
*/
7375
public function addAlias(
7476
string $interface,
75-
string $alias
76-
): void {
77+
string $alias,
78+
int $priority = 0
79+
): static {
7780
if (!isset($this->aliases[$interface])) {
78-
$this->aliases[$interface] = [];
81+
$this->aliases[$interface] = new NamespaceList();
7982
}
8083

81-
$this->aliases[$interface][$alias] = $alias;
84+
$this->aliases[$interface]->add($alias, $priority);
85+
return $this;
8286
}
8387

8488
/**
@@ -88,51 +92,97 @@ public function hasAlias(
8892
string $interface,
8993
string $alias
9094
): bool {
91-
return isset($this->aliases[$interface][$alias]);
95+
return
96+
isset($this->aliases[$interface]) &&
97+
$this->aliases[$interface]->has($alias);
9298
}
9399

94100
/**
95101
* Remove alias
102+
*
103+
* @return $this
96104
*/
97105
public function removeAlias(
98106
string $interface,
99107
string $alias
100-
): void {
101-
unset($this->aliases[$interface][$alias]);
108+
): static {
109+
if (isset($this->aliases[$interface])) {
110+
$this->aliases[$interface]->remove($alias);
111+
}
112+
113+
return $this;
102114
}
103115

104116
/**
105117
* Map namespace
106118
*/
107119
public function map(
108-
string $namespace
120+
string $namespace,
121+
bool $includeRoot = true
109122
): NamespaceList {
110123
$output = new NamespaceList();
111-
$this->applyMap($namespace, $output);
112-
113-
foreach ($this->aliases[$namespace] ?? [] as $alias) {
114-
$this->applyMap($alias, $output);
115-
}
116-
124+
$this->applyMap($namespace, $output, -1, $includeRoot);
117125
return $output;
118126
}
119127

120128
protected function applyMap(
121129
string $namespace,
122-
NamespaceList $namespaces
130+
NamespaceList $namespaces,
131+
int $priority = 0,
132+
bool $includeRoot = true
123133
): NamespaceList {
134+
// Import root
135+
if ($includeRoot) {
136+
$namespaces->add($namespace, $priority);
137+
}
138+
124139
$parts = explode('\\', $namespace);
125140
$inner = [];
126-
$namespaces->add($namespace, -1);
127141

128142
while (!empty($parts)) {
129143
$root = implode('\\', $parts);
130144

145+
// Import root maps
131146
if (isset($this->namespaces[$root])) {
132147
$mapTo = empty($inner) ? null : implode('\\', $inner);
133148
$namespaces->import($this->namespaces[$root], $mapTo, $namespace);
134149
}
135150

151+
152+
// Aliases
153+
$wild = false;
154+
$key = null;
155+
156+
if (
157+
isset($this->aliases[$root . '\\*']) &&
158+
// Wildcards only make sense for one level
159+
count($inner) <= 1
160+
) {
161+
$key = $root . '\\*';
162+
$wild = true;
163+
} elseif (isset($this->aliases[$root])) {
164+
$key = $root;
165+
}
166+
167+
if ($key !== null) {
168+
foreach ($this->aliases[$key] ?? [] as $priority => $alias) {
169+
$append = $inner;
170+
171+
if ($wild) {
172+
array_pop($append);
173+
}
174+
175+
if (!empty($append)) {
176+
$alias .= '\\' . implode('\\', $append);
177+
}
178+
179+
$this->applyMap($alias, $namespaces, $priority);
180+
}
181+
182+
return $namespaces;
183+
}
184+
185+
// Shift parts
136186
array_unshift($inner, array_pop($parts));
137187
}
138188

stubs/DecodeLabs/Archetype.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public static function registerCustomNormalizer(string $interface, callable $nor
3737
return static::$instance->registerCustomNormalizer(...func_get_args());
3838
}
3939
public static function map(string $root, string $namespace, int $priority = 0): void {}
40-
public static function alias(string $interface, string $alias): void {}
40+
public static function alias(string $interface, string $alias, int $priority = 0): void {}
4141
public static function resolve(string $interface, array|string|null $names = NULL, callable|string|null $default = NULL): string {
4242
return static::$instance->resolve(...func_get_args());
4343
}

0 commit comments

Comments
 (0)