Passed
Push — compile_injector ( 4c8324...7b0cfc )
by Akihito
02:04
created

PackageInjector::getInstance()   A

Complexity

Conditions 6
Paths 9

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 11
c 1
b 0
f 0
dl 0
loc 19
rs 9.2222
cc 6
nc 9
nop 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BEAR\Package\Injector;
6
7
use BEAR\AppMeta\AbstractAppMeta;
8
use BEAR\Package\LazyModule;
9
use BEAR\Package\Module;
10
use BEAR\Sunday\Extension\Application\AppInterface;
11
use Ray\Compiler\Annotation\Compile;
12
use Ray\Compiler\CompileInjector;
13
use Ray\Compiler\ScriptInjector;
14
use Ray\Di\AbstractModule;
15
use Ray\Di\Injector as RayInjector;
16
use Ray\Di\InjectorInterface;
17
use Symfony\Component\Cache\Adapter\AdapterInterface;
18
use Symfony\Contracts\Cache\CacheInterface;
19
20
use function assert;
21
use function is_bool;
22
use function is_dir;
23
use function mkdir;
24
use function str_replace;
25
26
final class PackageInjector
27
{
28
    /**
29
     * Serialized injector instances
30
     *
31
     * @var array<string, InjectorInterface>
32
     */
33
    private static array $instances;
34
35
    /**
36
     * @codeCoverageIgnore
37
     */
38
    private function __construct()
39
    {
40
    }
41
42
    public static function getInstance(AbstractAppMeta $meta, string $context, ?CacheInterface $cache): InjectorInterface
43
    {
44
        $injectorId = str_replace('\\', '_', $meta->name) . $context;
45
        if (isset(self::$instances[$injectorId])) {
46
            return self::$instances[$injectorId];
47
        }
48
49
        assert($cache instanceof AdapterInterface);
50
        /** @psalm-suppress all */
51
        [$injector, $fileUpdate] = $cache->getItem($injectorId)->get(); // @phpstan-ignore-line
52
        $isCacheableInjector = $injector instanceof ScriptInjector || ($injector instanceof InjectorInterface && $fileUpdate instanceof FileUpdate && $fileUpdate->isNotUpdated($meta));
53
        if (! $isCacheableInjector) {
54
            $injector = self::factory($meta, $context);
55
            $cache->save($cache->getItem($injectorId)->set([$injector, new FileUpdate($meta)]));
56
        }
57
58
        self::$instances[$injectorId] = $injector;
59
60
        return $injector;
61
    }
62
63
    public static function factory(AbstractAppMeta $meta, string $context, ?AbstractModule $overideModule = null): InjectorInterface
64
    {
65
        $scriptDir = $meta->tmpDir . '/di';
66
        ! is_dir($scriptDir) && ! @mkdir($scriptDir) && ! is_dir($scriptDir);
67
        $module = (new Module())($meta, $context);
68
69
        if ($overideModule instanceof AbstractModule) {
70
            $module->override($overideModule);
71
        }
72
73
        $injector = new RayInjector($module, $scriptDir);
74
        $isProd = $injector->getInstance('', Compile::class);
75
        assert(is_bool($isProd));
76
        if ($isProd) {
77
            $injector = new CompileInjector($scriptDir, new LazyModule($meta, $context, $scriptDir));
78
        }
79
80
        $injector->getInstance(AppInterface::class);
81
82
        return $injector;
83
    }
84
}
85