CompiledInjector   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 98
Duplicated Lines 0 %

Importance

Changes 7
Bugs 0 Features 0
Metric Value
eloc 32
c 7
b 0
f 0
dl 0
loc 98
rs 10
wmc 13

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __wakeup() 0 3 1
A registerLoader() 0 23 5
A __construct() 0 13 4
A getInstance() 0 23 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Ray\Compiler;
6
7
use Override;
0 ignored issues
show
Bug introduced by
The type Override was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
8
use Ray\Compiler\Exception\ScriptDirNotReadable;
9
use Ray\Compiler\Exception\Unbound;
10
use Ray\Di\Annotation\ScriptDir;
11
use Ray\Di\Name;
12
13
use function file_exists;
14
use function in_array;
15
use function is_dir;
16
use function is_readable;
17
use function realpath;
18
use function spl_autoload_register;
19
use function sprintf;
20
use function str_replace;
21
22
/**
23
 * Compiled Injector
24
 *
25
 * An injector that requires all bindings to be pre-compiled into PHP code.
26
 * Use Ray\Compiler\Compiler to compile the bindings.
27
 * Runtime compilation is not supported.
28
 *
29
 * @psalm-import-type ScriptDir from Types
30
 * @psalm-import-type Singletons from Types
31
 * @psalm-import-type ScriptDirs from Types
32
 */
33
final class CompiledInjector implements ScriptInjectorInterface
34
{
35
    /** @var ScriptDir */
36
    private readonly string $scriptDir;
37
38
    /**
39
     * Singleton instance container
40
     *
41
     * @var Singletons
0 ignored issues
show
Bug introduced by
The type Ray\Compiler\Singletons was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
42
     */
43
    private array $singletons = [];
44
45
    /**
46
     * @psalm-import-type ScriptDirs from Types
0 ignored issues
show
Bug introduced by
The type Ray\Compiler\ScriptDirs was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
47
     * @var ScriptDirs
48
     */
49
    private static $scriptDirs = [];
50
51
    /**
52
     * @param ScriptDir $scriptDir generated instance script folder path
53
     *
54
     * @psalm-suppress UnresolvableInclude
55
     * @ScriptDir
56
     */
57
    public function __construct(#[ScriptDir]
58
    string $scriptDir,)
59
    {
60
        $realPath = realpath($scriptDir);
61
        if ($realPath === false || ! is_dir($realPath) || ! is_readable($realPath)) {
62
            $message = sprintf('Script directory "%s" is not readable. See https://ray-di.github.io/Ray.Compiler/error/ScriptDirNotReadable', $scriptDir);
63
64
            throw new ScriptDirNotReadable($message);
65
        }
66
67
        /** @psalm-var ScriptDir $realPath */
68
        $this->scriptDir = $realPath;
0 ignored issues
show
Documentation Bug introduced by
It seems like $realPath of type string is incompatible with the declared type Ray\Di\Annotation\ScriptDir of property $scriptDir.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
Bug introduced by
The property scriptDir is declared read-only in Ray\Compiler\CompiledInjector.
Loading history...
69
        $this->registerLoader();
70
    }
71
72
    public function __wakeup()
73
    {
74
        $this->registerLoader();
75
    }
76
77
    /**
78
     * {@inheritDoc}
79
     *
80
     * @template T
81
     * @SuppressWarnings(PHPMD.UnusedLocalVariable) // @phpstan-ignore-line
82
     */
83
    #[Override]
84
    public function getInstance($interface, $name = Name::ANY)
85
    {
86
        $dependencyIndex = $interface . '-' . $name;
87
        if (isset($this->singletons[$dependencyIndex])) {
88
            return $this->singletons[$dependencyIndex];
89
        }
90
91
        $scriptFile = sprintf('%s/%s.php', $this->scriptDir, str_replace('\\', '_', $dependencyIndex));
92
        if (! file_exists($scriptFile)) {
93
            throw new Unbound($dependencyIndex); // Binding not found
94
        }
95
96
        /** @psalm-suppress  UnsupportedPropertyReferenceUsage */
97
        $singletons = &$this->singletons;
98
        $scriptDir = realpath($this->scriptDir);
99
100
        // $scriptDir, $Singletons, and $dependencyIndex can be used in the included file
101
        /** @var mixed $instance */
102
        $instance = require $scriptFile;
103
104
        /** @psalm-var T $instance */
105
        return $instance;
106
    }
107
108
    private function registerLoader(): void
109
    {
110
        $scriptDir = $this->scriptDir;
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->scriptDir of type string is incompatible with the declared type Ray\Di\Annotation\ScriptDir of property $scriptDir.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
111
        if (in_array($scriptDir, self::$scriptDirs, true)) {
0 ignored issues
show
Bug introduced by
self::scriptDirs of type Ray\Compiler\ScriptDirs is incompatible with the type array expected by parameter $haystack of in_array(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

111
        if (in_array($scriptDir, /** @scrutinizer ignore-type */ self::$scriptDirs, true)) {
Loading history...
112
            return;
113
        }
114
115
        if (self::$scriptDirs === []) {
0 ignored issues
show
introduced by
The condition self::scriptDirs === array() is always false.
Loading history...
116
            spl_autoload_register(
117
                // @codeCoverageIgnoreStart
118
                static function (string $class): void {
119
                    foreach (self::$scriptDirs as $scriptDir) {
120
                        $file = sprintf('%s/%s.php', $scriptDir, str_replace('\\', '_', $class));
121
                        if (file_exists($file)) {
122
                            require_once $file;
123
                        }
124
                    }
125
                },
126
                // @codeCoverageIgnoreEnd
127
            );
128
        }
129
130
        self::$scriptDirs[] = $scriptDir;
131
    }
132
}
133