Completed
Push — develop ( c2c595...5a8a22 )
by Baptiste
04:17
created

Compile::onChange()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 6
ccs 4
cts 4
cp 1
crap 1
rs 9.4285
c 0
b 0
f 0
1
<?php
2
declare(strict_types = 1);
3
4
namespace Innmind\Compose;
5
6
use Innmind\Url\PathInterface;
7
use Innmind\Immutable\{
8
    MapInterface,
9
    Set,
10
    Str
11
};
12
use Symfony\Component\Config\{
13
    ConfigCache,
14
    Resource\FileResource
15
};
16
use Psr\Container\ContainerInterface;
17
18
final class Compile
19
{
20
    private $cache;
21
    private $debug = false;
22
23 3
    public function __construct(PathInterface $cache)
24
    {
25 3
        $this->cache = Str::of((string) $cache)->rightTrim('/');
26 3
    }
27
28
    /**
29
     * The cached container will be recompiled if the definition file has changed
30
     * since the last compilation
31
     */
32 1
    public static function onChange(PathInterface $cache): self
33
    {
34 1
        $self = new self($cache);
35 1
        $self->debug = true;
36
37 1
        return $self;
38
    }
39
40
    /**
41
     * @param MapInterface<string, mixed> $arguments
42
     */
43 3
    public function __invoke(
44
        Loader $load,
45
        PathInterface $path,
46
        MapInterface $arguments
47
    ): ContainerInterface {
48 3
        $cachePath = sprintf(
49 3
            '%s/%s.php',
50 3
            $this->cache,
51 3
            md5((string) $path)
52
        );
53 3
        $cache = new ConfigCache($cachePath, $this->debug);
54
55 3
        if ($cache->isFresh()) {
56 1
            return require $cachePath;
57
        }
58
59 3
        $services = $load($path);
60 3
        $code = $this->generateCode($services);
61 3
        $cache->write($code, [new FileResource((string) $path)]);
62
63 3
        return require $cachePath;
64
    }
65
66 3
    private function generateCode(Services $services): string
67
    {
68 3
        $compiled = $services->compile();
69
70
        return <<<PHP
71
<?php
72
declare(strict_types = 1);
73
74
use Innmind\Compose\Exception\NotFound;
75
use Innmind\Immutable\MapInterface;
76
use Psr\Container\ContainerInterface;
77
78
return new class(\$arguments) implements ContainerInterface {
79
    private \$container;
80
81
    public function __construct(MapInterface \$arguments)
82
    {
83
        //wrapping is used to avoid access to public method of the real
84
        //compiled container, methods to build services are public so we
85
        //can access tunnelled arguments between dependencies
86 3
        \$this->container = $compiled
87
    }
88
89
    public function get(\$id): object
90
    {
91
        return \$this->container->get(\$id);
92
    }
93
94
    public function has(\$id): bool
95
    {
96
        return \$this->container->has(\$id);
97
    }
98
};
99
100
PHP;
101
    }
102
}
103