Skip to content

Commit

Permalink
Upgraded aliasing
Browse files Browse the repository at this point in the history
Signed-off-by: Tom Wright <[email protected]>
  • Loading branch information
betterthanclay committed Apr 29, 2024
1 parent d40f96e commit a428e48
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 24 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
* Improved namespace mapping algorithm
* Upgraded namespace aliases to mount at any level
* Enable recursive aliases
* Added priority to aliases

## v0.3.3 (2024-04-29)
* Fixed Veneer stubs in gitattributes

Expand Down
5 changes: 3 additions & 2 deletions src/Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,10 @@ public function map(
*/
public function alias(
string $interface,
string $alias
string $alias,
int $priority = 0
): void {
$this->getNamespaceMap()->addAlias($interface, $alias);
$this->getNamespaceMap()->addAlias($interface, $alias, $priority);
}


Expand Down
10 changes: 6 additions & 4 deletions src/NamespaceList.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@

namespace DecodeLabs\Archetype;

use ArrayIterator;
use Countable;
use DecodeLabs\Glitch\Dumpable;
use Generator;
use IteratorAggregate;

/**
Expand Down Expand Up @@ -88,15 +88,17 @@ public function import(
/**
* Get iterator
*
* @return ArrayIterator<int, string>
* @return Generator<int, string>
*/
public function getIterator(): ArrayIterator
public function getIterator(): Generator
{
uasort($this->namespaces, function ($a, $b) {
return $a <=> $b;
});

return new ArrayIterator(array_reverse(array_keys($this->namespaces)));
foreach (array_reverse($this->namespaces) as $namespace => $priority) {
yield $priority => $namespace;
}
}

/**
Expand Down
84 changes: 67 additions & 17 deletions src/NamespaceMap.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class NamespaceMap
protected array $namespaces = [];

/**
* @var array<string, array<string>>
* @var array<string, NamespaceList>
*/
protected array $aliases = [];

Expand Down Expand Up @@ -69,16 +69,20 @@ public function remove(

/**
* Add alias
*
* @return $this
*/
public function addAlias(
string $interface,
string $alias
): void {
string $alias,
int $priority = 0
): static {
if (!isset($this->aliases[$interface])) {
$this->aliases[$interface] = [];
$this->aliases[$interface] = new NamespaceList();
}

$this->aliases[$interface][$alias] = $alias;
$this->aliases[$interface]->add($alias, $priority);
return $this;
}

/**
Expand All @@ -88,51 +92,97 @@ public function hasAlias(
string $interface,
string $alias
): bool {
return isset($this->aliases[$interface][$alias]);
return
isset($this->aliases[$interface]) &&
$this->aliases[$interface]->has($alias);
}

/**
* Remove alias
*
* @return $this
*/
public function removeAlias(
string $interface,
string $alias
): void {
unset($this->aliases[$interface][$alias]);
): static {
if (isset($this->aliases[$interface])) {
$this->aliases[$interface]->remove($alias);
}

return $this;
}

/**
* Map namespace
*/
public function map(
string $namespace
string $namespace,
bool $includeRoot = true
): NamespaceList {
$output = new NamespaceList();
$this->applyMap($namespace, $output);

foreach ($this->aliases[$namespace] ?? [] as $alias) {
$this->applyMap($alias, $output);
}

$this->applyMap($namespace, $output, -1, $includeRoot);
return $output;
}

protected function applyMap(
string $namespace,
NamespaceList $namespaces
NamespaceList $namespaces,
int $priority = 0,
bool $includeRoot = true
): NamespaceList {
// Import root
if ($includeRoot) {
$namespaces->add($namespace, $priority);
}

$parts = explode('\\', $namespace);
$inner = [];
$namespaces->add($namespace, -1);

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

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


// Aliases
$wild = false;
$key = null;

if (
isset($this->aliases[$root . '\\*']) &&
// Wildcards only make sense for one level
count($inner) <= 1
) {
$key = $root . '\\*';
$wild = true;
} elseif (isset($this->aliases[$root])) {
$key = $root;
}

if ($key !== null) {
foreach ($this->aliases[$key] ?? [] as $priority => $alias) {
$append = $inner;

if ($wild) {
array_pop($append);
}

if (!empty($append)) {
$alias .= '\\' . implode('\\', $append);
}

$this->applyMap($alias, $namespaces, $priority);
}

return $namespaces;
}

// Shift parts
array_unshift($inner, array_pop($parts));
}

Expand Down
2 changes: 1 addition & 1 deletion stubs/DecodeLabs/Archetype.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public static function registerCustomNormalizer(string $interface, callable $nor
return static::$instance->registerCustomNormalizer(...func_get_args());
}
public static function map(string $root, string $namespace, int $priority = 0): void {}
public static function alias(string $interface, string $alias): void {}
public static function alias(string $interface, string $alias, int $priority = 0): void {}
public static function resolve(string $interface, array|string|null $names = NULL, callable|string|null $default = NULL): string {
return static::$instance->resolve(...func_get_args());
}
Expand Down

0 comments on commit a428e48

Please sign in to comment.