Completed
Push — app ( d2c122 )
by Akihito
02:39
created

AppInjector::__construct()   B

Complexity

Conditions 5
Paths 16

Size

Total Lines 19
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 5

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 19
ccs 17
cts 17
cp 1
rs 8.8571
cc 5
eloc 15
nc 16
nop 4
crap 5
1
<?php
2
/**
3
 * This file is part of the BEAR.Package package.
4
 *
5
 * @license http://opensource.org/licenses/MIT MIT
6
 */
7
namespace BEAR\Package;
8
9
use BEAR\Accept\Module\App;
10
use BEAR\AppMeta\AbstractAppMeta;
11
use BEAR\AppMeta\Meta;
12
use Doctrine\Common\Cache\FilesystemCache;
13
use Ray\Compiler\ScriptInjector;
14
use Ray\Di\AbstractModule;
15
use Ray\Di\Bind;
16
use Ray\Di\Injector;
17
use Ray\Di\InjectorInterface;
18
use Ray\Di\Name;
19
20
final class AppInjector implements InjectorInterface
21
{
22
    /**
23
     * @var AbstractAppMeta
24
     */
25
    private $appMeta;
26
27
    /**
28
     * @var string
29
     */
30
    private $context;
31
32
    /**
33
     * @var string
34
     */
35
    private $scriptDir;
36
37
    /**
38
     * @var string
39
     */
40
    private $appDir;
41
42
    /**
43
     * @var ScriptInjector
44
     */
45
    private $injector;
46
47
    /**
48
     * @var string
49
     */
50
    private $cacheSpace;
51
52 27
    public function __construct(string $name, string $context, AbstractAppMeta $appMeta = null, string $cacheSpace = '')
53
    {
54 27
        $this->context = $context;
55 27
        $this->appMeta = $appMeta instanceof AbstractAppMeta ? $appMeta : new Meta($name, $context);
56 27
        $this->cacheSpace = $cacheSpace;
57 27
        $scriptDir = $this->appMeta->tmpDir . '/di';
58 27
        ! \file_exists($scriptDir) && \mkdir($scriptDir);
59 27
        $this->scriptDir = $scriptDir;
60 27
        $appDir = $this->appMeta->tmpDir . '/app';
61 27
        ! \file_exists($appDir) && \mkdir($appDir);
62 27
        touch($appDir . '/.do_not_clear');
63 27
        $this->appDir = $appDir;
64 27
        $this->injector = new ScriptInjector($this->scriptDir, function () {
65 14
            return $this->getModule();
66 27
        });
67 27
        if (! $cacheSpace) {
68 19
            $this->clear();
69
        }
70 26
    }
71
72
    /**
73
     * {@inheritdoc}
74
     */
75 17
    public function getInstance($interface, $name = Name::ANY)
76
    {
77 17
        return $this->injector->getInstance($interface, $name);
78
    }
79
80 1
    public function getOverrideInstance(AbstractModule $module, $interface, $name = Name::ANY)
81
    {
82 1
        $appModule = clone $this->getModule();
83 1
        $appModule->override($module);
0 ignored issues
show
Documentation introduced by
$module is of type object<Ray\Di\AbstractModule>, but the function expects a object<self>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
84
85 1
        return (new Injector($appModule, $this->scriptDir))->getInstance($interface, $name);
86
    }
87
88 25
    public function clear()
89
    {
90 25
        if ((new Unlink)->once($this->appMeta->tmpDir)) {
91 20
            return;
92
        }
93 7
        ! is_dir($this->appMeta->tmpDir . '/di') && \mkdir($this->appMeta->tmpDir . '/di');
94 7
        file_put_contents($this->scriptDir . ScriptInjector::MODULE, serialize($this->getModule()));
95 5
    }
96
97 8
    public function getCachedInstance($interface, $name = Name::ANY)
98
    {
99 8
        $lockFile = $this->appMeta->appDir . '/composer.lock';
100 8
        $this->cacheSpace .= file_exists($lockFile) ? (string) filemtime($lockFile) : '';
101 8
        $cache = new FilesystemCache($this->appDir);
102 8
        $id = $interface . $name . $this->context . $this->cacheSpace;
103 8
        $instance = $cache->fetch($id);
104 8
        if ($instance) {
105 3
            return $instance;
106
        }
107 6
        $this->clear();
108 5
        $instance = $this->injector->getInstance($interface, $name);
109 5
        $cache->save($id, $instance);
110
111 5
        return $instance;
112
    }
113
114 16
    private function getModule() : AbstractModule
115
    {
116 16
        $module = (new Module)($this->appMeta, $this->context);
117
        /* @var AbstractModule $module */
118 14
        $container = $module->getContainer();
119 14
        (new Bind($container, InjectorInterface::class))->toInstance($this->injector);
120 14
        (new Bind($container, ''))->annotatedWith('cache_namespace')->toInstance($this->cacheSpace);
121
122 14
        return $module;
123
    }
124
}
125