Skip to content

Commit 5379835

Browse files
committed
does not discard inferior prefix lengths and orders candidates by prefix
length
1 parent a2d586f commit 5379835

File tree

2 files changed

+53
-30
lines changed

2 files changed

+53
-30
lines changed

lib/Adapter/Composer/ComposerClassToFile.php

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,16 @@ public function classToFileCandidates(ClassName $className): FilePathCandidates
3636
$this->resolveFile($candidates, $prefixes, $inflector, $className);
3737
}
3838

39+
// order with the longest prefixes first
40+
uksort($candidates, function ($prefix1, $prefix2) {
41+
return strlen($prefix2) <=> strlen($prefix1);
42+
});
43+
44+
// flatten to a single array
45+
$candidates = array_reduce($candidates, function ($candidates, $paths) {
46+
return array_merge($candidates, $paths);
47+
}, []);
48+
3949
return FilePathCandidates::fromFilePaths($candidates);
4050
}
4151

@@ -68,49 +78,55 @@ private function getStrategies(): array
6878

6979
private function resolveFile(&$candidates, array $prefixes, NameInflector $inflector, ClassName $className)
7080
{
71-
list($prefix, $files) = $this->getFileCandidates($className, $prefixes);
81+
$fileCandidates = $this->getFileCandidates($className, $prefixes);
82+
83+
foreach ($fileCandidates as $prefix => $files) {
84+
$prefixCandidates = [];
85+
foreach ($files as $file) {
86+
$prefixCandidates[] = $inflector->inflectToRelativePath($prefix, $className, $file);
87+
}
88+
89+
if (!isset($candidates[$prefix])) {
90+
$candidates[$prefix] = [];
91+
}
7292

73-
foreach ($files as $file) {
74-
$candidates[] = $inflector->inflectToRelativePath($prefix, $className, $file);
93+
$candidates[$prefix] = array_merge($candidates[$prefix], $prefixCandidates);
7594
}
7695
}
7796

7897
private function getFileCandidates(ClassName $className, array $prefixes)
7998
{
80-
$bestFiles = [null, []];
81-
$bestLength = 0;
99+
$candidates = [];
82100

83-
foreach ($prefixes as $prefix => $files) {
84-
$files = (array) $files;
85-
$files = array_map(function ($file) {
86-
if (!file_exists($file)) {
101+
foreach ($prefixes as $prefix => $paths) {
102+
$paths = (array) $paths;
103+
$paths = array_map(function ($path) {
104+
if (!file_exists($path)) {
87105
$this->logger->warning(sprintf(
88-
'Composer mapped directory "%s" does not exist', $file
106+
'Composer mapped path "%s" does not exist', $path
89107
));
90108

91-
return $file;
109+
return $path;
92110
}
93111

94-
return realpath($file);
95-
}, $files);
112+
return realpath($path);
113+
}, $paths);
96114

97-
if (empty($prefix) || $className->beginsWith($prefix)) {
98-
$length = strlen($prefix);
115+
if (is_int($prefix)) {
116+
$prefix = '';
117+
}
99118

100-
if ($length > $bestLength) {
101-
$bestFiles = array($prefix, $files);
102-
$bestLength = $length;
103-
}
119+
if ($prefix && false === $className->beginsWith($prefix)) {
120+
continue;
121+
}
122+
123+
if (!isset($candidates[$prefix])) {
124+
$candidates[$prefix] = [];
104125
}
105-
}
106126

107-
if (empty($bestFiles)) {
108-
throw new \RuntimeException(sprintf(
109-
'Could not find matching prefix for class name "%s", is it correctly defined in your composer file?',
110-
(string) $className
111-
));
127+
$candidates[$prefix] = array_merge($candidates[$prefix], $paths);
112128
}
113129

114-
return $bestFiles;
130+
return $candidates;
115131
}
116132
}

tests/Integration/Composer/ComposerClassToFileTest.php

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,14 @@ public function testPsr4Dev()
5151
/**
5252
* @testdox PSR-4 multiple matching prefixes
5353
*/
54-
public function testPsr4MultipleMatches()
54+
public function testPsr4MultipleMatchesLongestPrefixesFirst()
5555
{
5656
$this->loadExample('psr4-multiple-matching-prefixes.json');
57-
$this->assertClassNameToFilePath('Acme\\Test\\Foo\\Bar\\Class', ['psr4/tests/Class.php']);
57+
$this->assertClassNameToFilePath('Acme\\Test\\Foo\\Bar\\Class', [
58+
'psr4/tests/Class.php',
59+
'psr4/tests/foo/Bar/Class.php',
60+
'psr4/Foo/Bar/Class.php'
61+
]);
5862
}
5963

6064
/**
@@ -81,7 +85,10 @@ public function testPsr0()
8185
public function testPsr0AndPsr4()
8286
{
8387
$this->loadExample('psr0-psr4.json');
84-
$this->assertClassNameToFilePath('Acme\\Test\\Class', ['psr4/Class.php', 'psr0/Acme/Test/Class.php']);
88+
$this->assertClassNameToFilePath('Acme\\Test\\Class', [
89+
'psr4/Class.php',
90+
'psr0/Acme/Test/Class.php'
91+
]);
8592
}
8693

8794
/**
@@ -136,7 +143,7 @@ public function testClassmap()
136143
public function testIgnoresInvalidDirs()
137144
{
138145
$this->loadExample('invalid-dir.json');
139-
$this->logger->warning(Argument::containingString('Composer mapped directory'))->shouldBeCalledTimes(1);
146+
$this->logger->warning(Argument::containingString('Composer mapped path'))->shouldBeCalledTimes(1);
140147

141148
$this->assertClassNameToFilePath(
142149
'Acme\\Foo\\Generator',

0 commit comments

Comments
 (0)