-
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Autoloader.php
122 lines (110 loc) · 3.45 KB
/
Autoloader.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
<?php
/**
* Copyright 2021 Jeremy Presutti <Jeremy@Presutti.us>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
declare(strict_types=1);
namespace Feast;
/**
* Autoloader class PSR4 compliant
*/
class Autoloader
{
/** @var array<array> */
protected array $pathMappings = [];
/** @var string[] */
protected array $extensions = ['.php'];
/**
* Add path mapping for a namespace. - Replaces existing.
*
* @param string $namespace
* @param array $path
*/
public function addPathMapping(string $namespace, array $path): void
{
$this->pathMappings[$namespace] ??= [];
$this->pathMappings[$namespace] = array_merge($this->pathMappings[$namespace], $path);
}
/**
* Register the Autoloader with optional file extensions.
*
* @param string[] $extensions
*/
public function register(array $extensions = ['.php']): void
{
$this->extensions = $extensions;
spl_autoload_register([$this, 'loadClass'], true, true);
$this->addPathMapping(
'Psr',
[
'Feast\Psr'
]
);
}
/**
* Load class file by class name.
*
* @param string $class
*/
public function loadClass(string $class): void
{
/** @var array{0:array<string>,1:string} $path */
$path = $this->getMappings($class);
$this->loadFile($path[0], $path[1]);
}
/**
* Load file by Path list/Class name.
*
* @param array<string> $paths
* @param string $class
* @return bool
*/
protected function loadFile(array $paths, string $class): bool
{
foreach ($paths as $path) {
foreach ($this->extensions as $extension) {
$fullPath = str_replace('\\', DIRECTORY_SEPARATOR, $path . '\\' . $class) . $extension;
if (file_exists(APPLICATION_ROOT . $fullPath)) {
/** @noinspection PhpIncludeInspection */
/** @psalm-suppress UnresolvableInclude */
require_once(APPLICATION_ROOT . $fullPath);
return true;
}
}
}
return false;
}
/**
* Get path mappings by class name.
*
* @param string $class
* @return array
*/
protected function getMappings(string $class): array
{
$namespaceSplit = explode('\\', $class);
$sectionCount = count($namespaceSplit) - 1;
for ($i = $sectionCount; $i > 0; $i--) {
$newSplit = array_slice($namespaceSplit, 0, $i);
$postSplit = array_slice($namespaceSplit, $i);
$path = implode('\\', $newSplit);
if (isset($this->pathMappings[$path])) {
return [$this->pathMappings[$path], implode('\\', $postSplit)];
}
}
$class = array_pop($namespaceSplit);
$path = implode('\\', $namespaceSplit);
return [[$path], $class];
}
}