Issues (101)

src/di/Injector.php (3 issues)

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Ray\Di;
6
7
use Doctrine\Common\Annotations\AnnotationException;
8
use Ray\Aop\Compiler;
9
use Ray\Di\Exception\DirectoryNotWritable;
10
use Ray\Di\Exception\Untargeted;
11
12
use function assert;
13
use function file_exists;
14
use function is_dir;
15
use function is_writable;
16
use function spl_autoload_register;
17
use function sprintf;
18
use function str_replace;
19
use function sys_get_temp_dir;
20
21
/**
22
 * @psalm-import-type BindableInterface from Types
23
 * @psalm-import-type ModuleList from Types
24
 */
25
final class Injector implements InjectorInterface
26
{
27
    /** @var non-empty-string */
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-string at position 0 could not be parsed: Unknown type name 'non-empty-string' at position 0 in non-empty-string.
Loading history...
28
    private $classDir;
29
30
    /** @var Container */
31
    private $container;
32
33
    /**
34
     * @param AbstractModule|ModuleList|null $module Module(s)
0 ignored issues
show
The type Ray\Di\ModuleList 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...
35
     * @param string                         $tmpDir Temp directory for generated class
36
     */
37
    public function __construct($module = null, string $tmpDir = '')
38
    {
39
        /** @var non-empty-string $classDir */
40
        $classDir = is_dir($tmpDir) ? $tmpDir : sys_get_temp_dir();
41
        if (! is_writable($classDir)) {
42
            throw new DirectoryNotWritable($classDir); // @CodeCoverageIgnore
43
        }
44
45
        $this->classDir = $classDir;
46
        $this->container = (new ContainerFactory())($module, $this->classDir);
47
        // Bind injector (built-in bindings)
48
        (new Bind($this->container, InjectorInterface::class))->toInstance($this);
49
        $this->container->sort();
50
    }
51
52
    /**
53
     * Wakeup
54
     */
55
    public function __wakeup()
56
    {
57
        spl_autoload_register(
58
            function (string $class): void {
59
                $file = sprintf('%s/%s.php', $this->classDir, str_replace('\\', '_', $class));
60
                if (file_exists($file)) {
61
                    include $file; //@codeCoverageIgnore
62
                }
63
            }
64
        );
65
    }
66
67
    /**
68
     * {@inheritDoc}
69
     */
70
    public function getInstance($interface, $name = Name::ANY)
71
    {
72
        try {
73
            /** @psalm-suppress MixedAssignment */
74
            $instance = $this->container->getInstance($interface, $name);
75
        } catch (Untargeted $e) {
76
            /** @psalm-var class-string $interface */
77
            $this->bind($interface);
78
            /** @psalm-suppress MixedAssignment */
79
            $instance = $this->getInstance($interface, $name);
80
        }
81
82
        /** @psalm-suppress MixedReturnStatement */
83
        return $instance;
84
    }
85
86
    /**
87
     * @param BindableInterface $class
0 ignored issues
show
The type Ray\Di\BindableInterface 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...
88
     *
89
     * @throws AnnotationException
90
     */
91
    private function bind(string $class): void
92
    {
93
        new Bind($this->container, $class);
94
        $bound = $this->container->getContainer()[$class . '-' . Name::ANY];
95
        assert($bound instanceof Dependency);
96
        $this->container->weaveAspect(new Compiler($this->classDir), $bound)->getInstance($class);
97
    }
98
}
99