ComposerClassMap::listClassesInPsrMaps()   B
last analyzed

Complexity

Conditions 6
Paths 6

Size

Total Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
nc 6
nop 0
dl 0
loc 32
rs 8.7857
c 0
b 0
f 0
1
<?php
2
3
namespace Facade\Ignition\Support;
4
5
use Illuminate\Support\Str;
6
use Symfony\Component\Finder\Finder;
7
use Symfony\Component\Finder\SplFileInfo;
8
9
class ComposerClassMap
10
{
11
    /** @var \Composer\Autoload\ClassLoader|FakeComposer */
12
    protected $composer;
13
14
    /** @var string */
15
    protected $basePath;
16
17
    public function __construct(?string $autoloaderPath = null)
18
    {
19
        $autoloaderPath = $autoloaderPath ?? base_path('/vendor/autoload.php');
20
21
        if (file_exists($autoloaderPath)) {
22
            $this->composer = require $autoloaderPath;
23
        } else {
24
            $this->composer = new FakeComposer();
25
        }
26
        $this->basePath = app_path();
27
    }
28
29
    public function listClasses(): array
30
    {
31
        $classes = $this->composer->getClassMap();
32
33
        return array_merge($classes, $this->listClassesInPsrMaps());
34
    }
35
36
    public function searchClassMap(string $missingClass): ?string
37
    {
38
        foreach ($this->composer->getClassMap() as $fqcn => $file) {
39
            $basename = basename($file, '.php');
40
41
            if ($basename === $missingClass) {
42
                return $fqcn;
43
            }
44
        }
45
46
        return null;
47
    }
48
49
    public function listClassesInPsrMaps(): array
50
    {
51
        // TODO: This is incorrect. Doesnt list all fqcns. Need to parse namespace? e.g. App\LoginController is wrong
52
53
        $prefixes = array_merge(
54
            $this->composer->getPrefixes(),
55
            $this->composer->getPrefixesPsr4()
56
        );
57
58
        $classes = [];
59
60
        foreach ($prefixes as $namespace => $directories) {
61
            foreach ($directories as $directory) {
62
                if (file_exists($directory)) {
63
                    $files = (new Finder)
64
                        ->in($directory)
65
                        ->files()
66
                        ->name('*.php');
67
68
                    foreach ($files as $file) {
69
                        if ($file instanceof SplFileInfo) {
70
                            $fqcn = $this->getFullyQualifiedClassNameFromFile($namespace, $file);
71
72
                            $classes[$fqcn] = $file->getRelativePathname();
73
                        }
74
                    }
75
                }
76
            }
77
        }
78
79
        return $classes;
80
    }
81
82
    public function searchPsrMaps(string $missingClass): ?string
83
    {
84
        $prefixes = array_merge(
85
            $this->composer->getPrefixes(),
86
            $this->composer->getPrefixesPsr4()
87
        );
88
89
        foreach ($prefixes as $namespace => $directories) {
90
            foreach ($directories as $directory) {
91
                if (file_exists($directory)) {
92
                    $files = (new Finder)
93
                        ->in($directory)
94
                        ->files()
95
                        ->name('*.php');
96
97
                    foreach ($files as $file) {
98
                        if ($file instanceof SplFileInfo) {
99
                            $basename = basename($file->getRelativePathname(), '.php');
100
101
                            if ($basename === $missingClass) {
102
                                return $namespace.basename($file->getRelativePathname(), '.php');
103
                            }
104
                        }
105
                    }
106
                }
107
            }
108
        }
109
110
        return null;
111
    }
112
113
    protected function getFullyQualifiedClassNameFromFile(string $rootNamespace, SplFileInfo $file): string
114
    {
115
        $class = trim(str_replace($this->basePath, '', $file->getRealPath()), DIRECTORY_SEPARATOR);
116
117
        $class = str_replace(
118
            [DIRECTORY_SEPARATOR, 'App\\'],
119
            ['\\', app()->getNamespace()],
120
            ucfirst(Str::replaceLast('.php', '', $class))
121
        );
122
123
        return $rootNamespace.$class;
124
    }
125
}
126