Completed
Push — fix-injector ( 14ef9e )
by Akihito
02:15
created

Injector::__construct()   B

Complexity

Conditions 7
Paths 27

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 19
rs 8.8333
c 0
b 0
f 0
cc 7
nc 27
nop 4
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BEAR\Package;
6
7
use BEAR\AppMeta\Meta;
8
use BEAR\Package\Context\Provider\ProdCacheProvider;
9
use BEAR\Package\Provide\Boot\ScriptinjectorModule;
10
use BEAR\Sunday\Extension\Application\AppInterface;
11
use Doctrine\Common\Cache\ArrayCache;
12
use Doctrine\Common\Cache\Cache;
13
use Doctrine\Common\Cache\ChainCache;
14
use Ray\Compiler\ScriptInjector;
15
use Ray\Di\Injector as RayInjector;
16
use Ray\Di\InjectorInterface;
17
18
final class Injector implements InjectorInterface
19
{
20
    /**
21
     * Injector cache for unit testing
22
     *
23
     * @var array<InjectorInterface>
24
     */
25
    private static $cache;
26
27
    /**
28
     * @var InjectorInterface
29
     */
30
    private $injector;
31
32
    public function __construct(string $appName, string $context, string $appDir, string $cacheNamespace = '')
33
    {
34
        $meta = new Meta($appName, $context, $appDir);
35
        $scriptDir = $meta->tmpDir . '/di';
36
        ! is_dir($scriptDir) && ! @mkdir($scriptDir) && ! is_dir($scriptDir);
37
        $cacheDir = $meta->tmpDir . '/cache';
38
        ! is_dir($cacheDir) && ! @mkdir($cacheDir) && ! is_dir($cacheDir);
39
        $id = $context . $cacheNamespace;
40
        if (isset(self::$cache[$id])) {
41
            $this->injector = unserialize(self::$cache[$id]); // activation
42
43
            return;
44
        }
45
        $cache = (new ProdCacheProvider($meta, $cacheNamespace))->get();
46
        $injector = $cache->fetch(InjectorInterface::class);
47
        $this->injector = $injector instanceof InjectorInterface ? $injector : $this->getInjector($meta, $context, $cacheNamespace, $cache, $scriptDir);
48
        $this->injector->getInstance(AppInterface::class); // cache App as a singleton
49
        self::$cache[$id] = serialize($this->injector);
50
    }
51
52
    /**
53
     * {@inheritdoc}
54
     */
55
    public function getInstance($interface, $name = '')
56
    {
57
        return $this->injector->getInstance($interface, $name);
58
    }
59
60
    private function getInjector(Meta $meta, string $context, string $cacheNamespace, ChainCache $firstCache, string $scriptDir) : InjectorInterface
61
    {
62
        $module = (new Module)($meta, $context, $cacheNamespace);
63
        $rayInjector = new RayInjector($module, $scriptDir);
64
        $isDev = $rayInjector->getInstance(Cache::class) instanceof ArrayCache;
65
        if ($isDev) {
66
            return $rayInjector;
67
        }
68
        $injector = new ScriptInjector($scriptDir, function () use ($scriptDir, $module) {
69
            return new ScriptinjectorModule($scriptDir, $module);
70
        });
71
        $injector->getInstance(AppInterface::class); // cache App as a singleton
72
        $firstCache->save(InjectorInterface::class, $injector);
73
74
        return $injector;
75
    }
76
}
77