Skip to content

Commit 2e66d9b

Browse files
committed
chore: add test to vendor resolver
1 parent 39e23ac commit 2e66d9b

3 files changed

Lines changed: 93 additions & 7 deletions

File tree

docs/phpmd.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Issues detected: 9
3636
| <span class="prio3">3</span> | src/Element/Inline/Input.php | 36 | [TooManyFields](https://phpmd.org/rules/codesize.html#toomanyfields) | The class Input has 28 fields. Consider redesigning Input to keep the number of fields under 15. |
3737
| <span class="prio3">3</span> | src/Element/Inline/Input.php | 36 | [ExcessiveClassComplexity](https://phpmd.org/rules/codesize.html#excessiveclasscomplexity) | The class Input has an overall complexity of 50 which is very high. The configured complexity threshold is 50. |
3838
| <span class="prio3">3</span> | src/Element/Inline/Textarea.php | 36 | [TooManyFields](https://phpmd.org/rules/codesize.html#toomanyfields) | The class Textarea has 16 fields. Consider redesigning Textarea to keep the number of fields under 15. |
39-
| <span class="prio3">3</span> | src/Trait/ClassResolverTrait.php | 45 | [CyclomaticComplexity](https://phpmd.org/rules/codesize.html#cyclomaticcomplexity) | The method getElementByQualifiedName() has a Cyclomatic Complexity of 12. The configured cyclomatic complexity threshold is 10. |
39+
| <span class="prio3">3</span> | src/Trait/ClassResolverTrait.php | 44 | [CyclomaticComplexity](https://phpmd.org/rules/codesize.html#cyclomaticcomplexity) | The method getElementByQualifiedName() has a Cyclomatic Complexity of 12. The configured cyclomatic complexity threshold is 10. |
4040
| <span class="prio3">3</span> | src/Trait/GlobalAttributesTrait.php | 19 | [ExcessivePublicCount](https://phpmd.org/rules/codesize.html#excessivepubliccount) | The trait GlobalAttributesTrait has 48 public methods and attributes. Consider reducing the number of public items to less than 45. |
4141

4242
Issues detected: 15
@@ -137,4 +137,4 @@ Issues detected: 76
137137

138138
Issues detected: 8
139139

140-
Sat Jul 12 02:18:18 PM CEST 2025
140+
Sat Jul 12 05:47:35 PM CEST 2025

src/Trait/ClassResolverTrait.php

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ trait ClassResolverTrait
2121
public function getClassesImplementingInterface(string $interface): array
2222
{
2323
// Ensure all classes are loaded before scanning
24-
$projectRoot = $this->getProjectRoot();
25-
$this->loadAllPhpFiles($projectRoot . '/src');
24+
$this->loadAllRelevantPhpFiles();
2625

2726
$classes = get_declared_classes();
2827
$implementingClasses = [];
@@ -46,9 +45,8 @@ public function getElementByQualifiedName(string $qualifiedName): ?string
4645
{
4746
$elementClasses = [];
4847

49-
$projectRoot = $this->getProjectRoot();
48+
$this->loadAllRelevantPhpFiles();
5049

51-
$this->loadAllPhpFiles($projectRoot . '/src/Element');
5250
foreach (get_declared_classes() as $class) {
5351
if (is_subclass_of($class, HTMLElementDelegator::class) || \is_subclass_of(
5452
$class,
@@ -77,11 +75,42 @@ public function getElementByQualifiedName(string $qualifiedName): ?string
7775
return null;
7876
}
7977

78+
/**
79+
* Load all relevant PHP files for class scanning.
80+
*/
81+
private function loadAllRelevantPhpFiles(): void
82+
{
83+
$projectRoot = $this->getProjectRoot();
84+
$packageRoot = $this->getPackageRoot();
85+
86+
// Always load package classes
87+
$this->loadAllPhpFiles($packageRoot . '/src');
88+
89+
// Try to load project classes if they exist
90+
$projectSrcPath = $projectRoot . '/src';
91+
if (is_dir($projectSrcPath)) {
92+
$this->loadAllPhpFiles($projectSrcPath);
93+
}
94+
}
95+
96+
/**
97+
* Get the package root directory.
98+
*/
99+
private function getPackageRoot(): string
100+
{
101+
// The package root is always relative to this file's location
102+
return dirname(__DIR__, 2);
103+
}
104+
80105
/**
81106
* Recursively scan a directory for PHP files and require them.
82107
*/
83108
private function loadAllPhpFiles(string $directory): void
84109
{
110+
if (! is_dir($directory)) {
111+
return; // Skip if directory doesn't exist
112+
}
113+
85114
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory));
86115

87116
foreach ($files as $file) {
@@ -108,7 +137,7 @@ private function getProjectRoot(): string
108137
// When used in development (package root)
109138
__DIR__ . '/../../vendor/autoload.php',
110139
// Fallback: traverse up the directory tree looking for composer.json
111-
$this->findComposerRoot(__DIR__)
140+
$this->findComposerRoot(__DIR__),
112141
];
113142

114143
foreach ($possiblePaths as $path) {
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
use Html\Trait\ClassResolverTrait;
4+
5+
// Create a test class that uses the trait
6+
class TestClassResolver
7+
{
8+
use ClassResolverTrait;
9+
10+
public function callGetProjectRoot()
11+
{
12+
return $this->getProjectRoot();
13+
}
14+
15+
public function callLoadAllRelevantPhpFiles()
16+
{
17+
return $this->loadAllRelevantPhpFiles();
18+
}
19+
}
20+
21+
test('can get project root directory', function () {
22+
$testResolver = new TestClassResolver();
23+
24+
$projectRoot = $testResolver->callGetProjectRoot();
25+
26+
expect($projectRoot)
27+
->toBeString()
28+
->and($projectRoot)
29+
->not->toBeEmpty()
30+
->and(is_dir($projectRoot))
31+
->toBeTrue();
32+
});
33+
34+
test('can load all relevant PHP files without throwing exception', function () {
35+
$testResolver = new TestClassResolver();
36+
37+
expect(fn () => $testResolver->callLoadAllRelevantPhpFiles())
38+
->not->toThrow(Exception::class);
39+
});
40+
41+
test('project root contains vendor directory', function () {
42+
$testResolver = new TestClassResolver();
43+
44+
$vendorPath = $testResolver->callGetProjectRoot();
45+
expect(is_dir($vendorPath))
46+
->toBeTrue();
47+
});
48+
49+
test('project root contains autoload.php', function () {
50+
$testResolver = new TestClassResolver();
51+
52+
$projectRoot = $testResolver->callGetProjectRoot();
53+
$autoloadPath = $projectRoot . '/autoload.php';
54+
55+
expect(file_exists($autoloadPath))
56+
->toBeTrue();
57+
});

0 commit comments

Comments
 (0)