Completed
Push — master ( 0f0da2...360bf1 )
by Matthieu
01:46 queued 01:43
created

SourceCache::addDefinition()   A

Complexity

Conditions 1
Paths 1

Duplication

Lines 0
Ratio 0 %

Size

Total Lines 4
Code Lines 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace DI\Definition\Source;
4
5
use DI\Definition\AutowireDefinition;
6
use DI\Definition\Definition;
7
use DI\Definition\ObjectDefinition;
8
9
/**
10
 * Decorator that caches another definition source.
11
 *
12
 * @author Matthieu Napoli <[email protected]>
13
 */
14
class SourceCache implements DefinitionSource, MutableDefinitionSource
15
{
16
    /**
17
     * @var string
18
     */
19
    const CACHE_KEY = 'php-di.definitions.';
20
21
    /**
22
     * @var DefinitionSource
23
     */
24
    private $cachedSource;
25
26
    public function __construct(DefinitionSource $cachedSource)
27
    {
28
        $this->cachedSource = $cachedSource;
29
    }
30
31
    public function getDefinition(string $name)
32
    {
33
        $definition = apcu_fetch(self::CACHE_KEY . $name);
34
35
        if ($definition === false) {
36
            $definition = $this->cachedSource->getDefinition($name);
37
38
            // Update the cache
39
            if ($this->shouldBeCached($definition)) {
40
                apcu_store(self::CACHE_KEY . $name, $definition);
41
            }
42
        }
43
44
        return $definition;
45
    }
46
47
    /**
48
     * Used only for the compilation so we can skip the cache safely.
49
     */
50
    public function getDefinitions() : array
51
    {
52
        return $this->cachedSource->getDefinitions();
53
    }
54
55
    public static function isSupported() : bool
56
    {
57
        return function_exists('apcu_fetch')
58
            && ini_get('apc.enabled')
59
            && ! ('cli' === PHP_SAPI && ! ini_get('apc.enable_cli'));
60
    }
61
62
    public function addDefinition(Definition $definition)
63
    {
64
        throw new \LogicException('You cannot set a definition at runtime on a container that has caching enabled. Doing so would risk caching the definition for the next execution, where it might be different. You can either put your definitions in a file, remove the cache or ->set() a raw value directly (PHP object, string, int, ...) instead of a PHP-DI definition.');
65
    }
66
67
    private function shouldBeCached(Definition $definition = null) : bool
68
    {
69
        return
70
            // Cache missing definitions
71
            ($definition === null)
72
            // Object definitions are used with `make()`
73
            || ($definition instanceof ObjectDefinition)
74
            // Autowired definitions cannot be all compiled and are used with `make()`
75
            || ($definition instanceof AutowireDefinition);
76
    }
77
}
78