Cache   A
last analyzed

Complexity

Total Complexity 5

Size/Duplication

Total Lines 70
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
eloc 39
dl 0
loc 70
ccs 23
cts 23
cp 1
rs 10
c 0
b 0
f 0
wmc 5

4 Methods

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