Compiler   A
last analyzed

Complexity

Total Complexity 4

Size/Duplication

Total Lines 43
Duplicated Lines 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
eloc 19
c 5
b 0
f 0
dl 0
loc 43
rs 10
wmc 4

1 Method

Rating   Name   Duplication   Size   Complexity  
A compile() 0 34 4
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Ray\Compiler;
6
7
use Ray\Compiler\Exception\CompileLockFailed;
8
use Ray\Di\AbstractModule;
9
use Ray\Di\AcceptInterface;
10
use Ray\Di\Annotation\ScriptDir;
11
use Ray\Di\ContainerFactory;
12
use Ray\Di\DependencyInterface;
13
14
use function assert;
15
use function fclose;
16
use function flock;
17
use function fopen;
18
use function is_string;
19
20
use const LOCK_EX;
21
use const LOCK_UN;
22
23
/**
24
 *  Module Compiler
25
 *
26
 *  Compiles module bindings into PHP files for CompiledInjector.
27
 *  The compilation process includes:
28
 *  - Acquiring a file lock to ensure thread safety
29
 *  - Converting dependencies into PHP scripts using CompileVisitor
30
 *  - Saving compiled scripts to the target directory
31
 *
32
 * @psalm-import-type ScriptDir from Types
33
 */
34
final class Compiler
35
{
36
    /**
37
     * Compiles a given module into Scripts
38
     *
39
     * @param ScriptDir $scriptDir
40
     *
41
     * @SuppressWarnings(PHPMD.UnusedFormalParameter) // @phpstan-ignore-line
42
     */
43
    public function compile(AbstractModule $module, string $scriptDir): Scripts
44
    {
45
        $module->override(new CompilerModule($scriptDir));
46
47
        // Lock
48
        $fp = fopen($scriptDir . '/compile.lock', 'a+');
49
        if ($fp === false || ! flock($fp, LOCK_EX)) {
50
            // @codeCoverageIgnoreStart
51
            if ($fp !== false) {
52
                fclose($fp);
53
            }
54
55
            throw new CompileLockFailed($scriptDir);
56
            // @codeCoverageIgnoreEnd
57
        }
58
59
        $scripts = new Scripts();
60
        $container = (new ContainerFactory())($module, $scriptDir);
61
        // Compile dependencies
62
        $compileVisitor = new CompileVisitor($container);
63
        $container->map(static function (DependencyInterface $dependency, string $key) use ($scripts, $compileVisitor): DependencyInterface {
64
            assert($dependency instanceof AcceptInterface);
65
            $script = $dependency->accept($compileVisitor);
66
            assert(is_string($script));
67
            $scripts->add($key, $script);
68
69
            return $dependency;
70
        });
71
        $scripts->save($scriptDir);
72
        // Unlock
73
        flock($fp, LOCK_UN);
74
        fclose($fp);
75
76
        return $scripts;
77
    }
78
}
79