1
0
mirror of https://github.com/danog/class-finder.git synced 2024-11-27 04:24:41 +01:00

Select the best possible namespace instead of the last one to match any of the elements.

This commit is contained in:
Hayden Pierce 2018-09-02 11:14:22 -05:00
parent 88b389e489
commit b74b0b02c1
2 changed files with 52 additions and 13 deletions

View File

@ -20,16 +20,7 @@ class PSR4Finder implements FinderInterface
*/
public function findClasses($namespace)
{
$composerNamespaces = $this->factory->getPSR4Namespaces();
/** @var PSR4Namespace $bestNamespace */
$bestNamespace = array_reduce($composerNamespaces, function($carry, PSR4Namespace $potentialNamespace) use ($namespace) {
if ($potentialNamespace->matches($namespace)) {
return $potentialNamespace;
} else {
return $carry;
}
}, null);
$bestNamespace = $this->findBestPSR4Namespace($namespace);
if ($bestNamespace instanceof PSR4Namespace) {
return $bestNamespace->findClasses($namespace);
@ -40,4 +31,31 @@ class PSR4Finder implements FinderInterface
));
}
}
/**
* @param $namespace
* @return PSR4Namespace
*/
private function findBestPSR4Namespace($namespace)
{
$composerNamespaces = $this->factory->getPSR4Namespaces();
$carry = new \stdClass();
$carry->highestMatchingSegments = 0;
$carry->bestNamespace = null;
/** @var PSR4Namespace $bestNamespace */
$bestNamespace = array_reduce($composerNamespaces, function ($carry, PSR4Namespace $potentialNamespace) use ($namespace) {
$matchingSegments = $potentialNamespace->countMatchingNamespaceSegments($namespace);
if ($matchingSegments > $carry->highestMatchingSegments) {
$carry->highestMatchingSegments = $matchingSegments;
$carry->bestNamespace = $potentialNamespace;
}
return $carry;
}, $carry);
return $bestNamespace->bestNamespace;
}
}

View File

@ -14,7 +14,28 @@ class PSR4Namespace
$this->directories = $directories;
}
public function matches($namespace)
/**
* Determines how many namespace segments match the internal namespace. This is useful because multiple namespaces
* may technically match a registered namespace root, but one of the matches may be a better match. Namespaces that
* match, but are not _the best_ match are incorrect matches. TestApp1\\ is **not** the best match when searching for
* namespace TestApp1\\Multi\\Foo if TestApp1\\Multi was explicitly registered.
*
* PSR4Namespace $a;
* $a->namespace = "TestApp1\\";
* $a->countMatchingNamespaceSegments("TestApp1\\Multi") -> 1, TestApp1 matches.
*
* PSR4Namespace $b;
* $b->namespace = "TestApp1\\Multi";
* $b->countMatchingNamespaceSegments("TestApp1\\Multi") -> 2, TestApp1\\Multi matches
*
* PSR4Namespace $c;
* $c->namespace = "HaydenPierce\\Foo\\Bar";
* $c->countMatchingNamespaceSegments("TestApp1\\Multi") -> 0, No matches.
*
* @param $namespace
* @return int
*/
public function countMatchingNamespaceSegments($namespace)
{
$namespaceFragments = explode('\\', $namespace);
$undefinedNamespaceFragments = [];
@ -23,13 +44,13 @@ class PSR4Namespace
$possibleNamespace = implode('\\', $namespaceFragments) . '\\';
if($this->namespace === $possibleNamespace){
return true;
return count(explode('\\', $possibleNamespace));
}
array_unshift($undefinedNamespaceFragments, array_pop($namespaceFragments));
}
return false;
return 0;
}
public function findClasses($namespace)