Completed
Push — spike ( 0c7ee3...52d02b )
by Akihito
02:12
created

Injector::factory()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 20
rs 9.6
c 0
b 0
f 0
cc 4
nc 6
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
19
{
20
    /**
21
     * Injector serialized instances
22
     *
23
     * @var array<string>
24
     */
25
    private static $instances;
26
27
    private function __construct()
28
    {
29
    }
30
31
    public static function getInstance(string $appName, string $context, string $appDir, string $cacheNamespace = '') : InjectorInterface
32
    {
33
        $injectorId = $appName . $context . $cacheNamespace;
34
        if (isset(self::$instances[$injectorId])) {
35
            return unserialize(self::$instances[$injectorId], ['allowed_classes' => true]); // __wakeup the injector
36
        }
37
        $meta = new Meta($appName, $context, $appDir);
38
        $cache = (new ProdCacheProvider($meta, $injectorId))->get();
39
        $cachedInjector = $cache->fetch(InjectorInterface::class);
40
        $injector = $cachedInjector instanceof InjectorInterface ? $cachedInjector : self::factory($meta, $context, $cacheNamespace, $cache);
41
        self::$instances[$injectorId] = serialize($injector);
42
43
        return $injector;
44
    }
45
46
    private static function factory(Meta $meta, string $context, string $cacheNamespace, ChainCache $cache) : InjectorInterface
47
    {
48
        $scriptDir = $meta->tmpDir . '/di';
49
        ! is_dir($scriptDir) && ! @mkdir($scriptDir) && ! is_dir($scriptDir);
50
        $module = (new Module)($meta, $context, $cacheNamespace);
51
        $rayInjector = new RayInjector($module, $scriptDir);
52
        $isDev = $rayInjector->getInstance(Cache::class) instanceof ArrayCache;
53
        if ($isDev) {
54
            $rayInjector->getInstance(AppInterface::class);
55
56
            return $rayInjector;
57
        }
58
        $scriptInjector = new ScriptInjector($scriptDir, function () use ($scriptDir, $module) {
59
            return new ScriptinjectorModule($scriptDir, $module);
60
        });
61
        $scriptInjector->getInstance(AppInterface::class); // cache App as a singleton
62
        $cache->save(InjectorInterface::class, $scriptInjector);
63
64
        return $scriptInjector;
65
    }
66
}
67