Completed
Pull Request — master (#239)
by Freek
04:47 queued 03:20
created

ComposerClassMap::listClassesInPsrMaps()   B

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