Autoloader::register()   B
last analyzed

Complexity

Conditions 7
Paths 3

Size

Total Lines 30
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 0
Metric Value
cc 7
eloc 13
nc 3
nop 3
dl 0
loc 30
ccs 0
cts 22
cp 0
crap 56
rs 8.8333
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\ORM\Mapping\Factory;
6
7
use Closure;
8
use InvalidArgumentException;
9
use const DIRECTORY_SEPARATOR;
10
use function call_user_func;
11
use function file_exists;
12
use function get_class;
13
use function gettype;
14
use function is_callable;
15
use function is_object;
16
use function ltrim;
17
use function spl_autoload_register;
18
use function sprintf;
19
use function str_replace;
20
use function strlen;
21
use function strpos;
22
use function substr;
23
24
class Autoloader
25
{
26
    /**
27
     * Resolves ClassMetadata class name to a filename based on the following pattern.
28
     *
29
     * 1. Remove Metadata namespace from class name.
30
     * 2. Remove namespace separators from remaining class name.
31
     * 3. Return PHP filename from metadata-dir with the result from 2.
32
     *
33
     * @throws InvalidArgumentException
34
     */
35
    public static function resolveFile(string $metadataDir, string $metadataNamespace, string $className) : string
36
    {
37
        if (strpos($className, $metadataNamespace) !== 0) {
38
            throw new InvalidArgumentException(
39
                sprintf('The class "%s" is not part of the metadata namespace "%s"', $className, $metadataNamespace)
40
            );
41
        }
42
43
        // remove metadata namespace from class name
44
        $classNameRelativeToMetadataNamespace = substr($className, strlen($metadataNamespace));
45
46
        // remove namespace separators from remaining class name
47
        $fileName = str_replace('\\', '', $classNameRelativeToMetadataNamespace);
48
49
        return $metadataDir . DIRECTORY_SEPARATOR . $fileName . '.php';
50
    }
51
52
    /**
53
     * Registers and returns autoloader callback for the given metadata dir and namespace.
54
     *
55
     * @param callable|null $notFoundCallback Invoked when the proxy file is not found.
56
     *
57
     * @throws InvalidArgumentException
58
     */
59
    public static function register(
60
        string $metadataDir,
61
        string $metadataNamespace,
62
        ?callable $notFoundCallback = null
63
    ) : Closure {
64
        $metadataNamespace = ltrim($metadataNamespace, '\\');
65
66
        if (! ($notFoundCallback === null || is_callable($notFoundCallback))) {
67
            $type = is_object($notFoundCallback) ? get_class($notFoundCallback) : gettype($notFoundCallback);
68
69
            throw new InvalidArgumentException(
70
                sprintf('Invalid \$notFoundCallback given: must be a callable, "%s" given', $type)
71
            );
72
        }
73
74
        $autoloader = static function ($className) use ($metadataDir, $metadataNamespace, $notFoundCallback) {
75
            if (strpos($className, $metadataNamespace) === 0) {
76
                $file = Autoloader::resolveFile($metadataDir, $metadataNamespace, $className);
77
78
                if ($notFoundCallback && ! file_exists($file)) {
79
                    call_user_func($notFoundCallback, $metadataDir, $metadataNamespace, $className);
80
                }
81
82
                require $file;
83
            }
84
        };
85
86
        spl_autoload_register($autoloader);
87
88
        return $autoloader;
89
    }
90
}
91