Completed
Push — master ( 88792f...ba8ac8 )
by Karsten
08:30 queued 06:31
created

CachedEntityConfigLookUp   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 138
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 82.93%

Importance

Changes 0
Metric Value
wmc 14
lcom 1
cbo 3
dl 0
loc 138
ccs 34
cts 41
cp 0.8293
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 1
A fetchFromCache() 0 13 4
A saveToCache() 0 11 3
A isCacheFresh() 0 12 2
A getEntityConfig() 0 15 1
A loadOrCreate() 0 15 3
1
<?php
2
/**
3
 * File was created 06.10.2015 06:25
4
 */
5
6
namespace PeekAndPoke\Component\Slumber\Core\LookUp;
7
8
use Doctrine\Common\Cache\Cache;
9
10
/**
11
 * @author Karsten J. Gerber <[email protected]>
12
 */
13
class CachedEntityConfigLookUp extends DelegatingEntityConfigReader
14
{
15
    /** @var Cache */
16
    private $cache;
17
    /** @var string */
18
    private $prefix;
19
    /** @var bool */
20
    private $debug;
21
22
    /**
23
     * We have another level of caching here
24
     *
25
     * @var array
26
     */
27
    private $known = [];
28
29
    /**
30
     * @param EntityConfigReader $delegate
31
     * @param Cache              $cache
32
     * @param string             $prefix
33
     * @param bool               $debug
34
     */
35 1
    public function __construct(EntityConfigReader $delegate, Cache $cache, $prefix = '[Slumber]@', $debug = false)
36
    {
37 1
        parent::__construct($delegate);
38
39 1
        $this->cache  = $cache;
40 1
        $this->prefix = $prefix;
41 1
        $this->debug  = $debug;
42 1
    }
43
44
    /**
45
     * @param \ReflectionClass $cls
46
     *
47
     * @return PropertyMarkedForSlumber[]
48
     */
49 1
    public function getEntityConfig(\ReflectionClass $cls)
50
    {
51 1
        $cacheKey = $this->prefix . $cls->name;
52
53 1
        return $this->loadOrCreate(
54 1
            $cacheKey,
55 1
            function () use ($cacheKey, $cls) {
56 1
                return $this->fetchFromCache($cacheKey, $cls);
57 1
            },
58 1
            function () use ($cls) {
59 1
                return $this->delegate->getEntityConfig($cls);
60 1
            },
61 1
            $cls
62
        );
63
    }
64
65
    /**
66
     * @param string           $cacheKey
67
     * @param \Closure         $fetcher
68
     * @param \Closure         $creator
69
     * @param \ReflectionClass $class
70
     *
71
     * @return mixed
72
     */
73 1
    private function loadOrCreate($cacheKey, \Closure $fetcher, \Closure $creator, \ReflectionClass $class)
74
    {
75 1
        if (isset($this->known[$cacheKey])) {
76
            return $this->known[$cacheKey];
77
        }
78
79
        /** @var EntityConfig $cacheData */
80 1
        $cacheData = $fetcher();
81 1
        if (false === $cacheData) {
82 1
            $cacheData = $creator();
83 1
            $this->saveToCache($cacheKey, $cacheData, $class);
84
        }
85
86 1
        return $this->known[$cacheKey] = $cacheData;
87
    }
88
89
    /**
90
     * Fetches a value from the cache.
91
     *
92
     * @param string           $rawCacheKey The cache key.
93
     * @param \ReflectionClass $class       The related class.
94
     *
95
     * @return mixed The cached value or false when the value is not in cache.
96
     */
97 1
    private function fetchFromCache($rawCacheKey, \ReflectionClass $class)
98
    {
99 1
        $cacheKey = $this->prefix . $rawCacheKey;
100
101 1
        if (($data = $this->cache->fetch($cacheKey)) !== false) {
102
            /** @noinspection NestedPositiveIfStatementsInspection */
103
            if (! $this->debug || $this->isCacheFresh($cacheKey, $class)) {
104
                return $data;
105
            }
106
        }
107
108 1
        return false;
109
    }
110
111
    /**
112
     * Saves a value to the cache.
113
     *
114
     * @param string           $rawCacheKey The cache key.
115
     * @param mixed            $value       The value.
116
     * @param \ReflectionClass $class
117
     */
118 1
    private function saveToCache($rawCacheKey, $value, \ReflectionClass $class)
119
    {
120 1
        $cacheKey = $this->prefix . $rawCacheKey;
121 1
        $this->cache->save($cacheKey, $value);
122
123
        // in debug mode record the creation time of the entry
124 1
        if ($this->debug && false !== $filename = $class->getFileName()) {
125
126 1
            $this->cache->save('[C]' . $cacheKey, filemtime($filename));
127
        }
128 1
    }
129
130
    /**
131
     * Checks if the cache is fresh.
132
     *
133
     * @param string           $cacheKey
134
     * @param \ReflectionClass $class
135
     *
136
     * @return boolean
137
     */
138
    private function isCacheFresh($cacheKey, \ReflectionClass $class)
139
    {
140
        if (false === $filename = $class->getFileName()) {
141
            return true;
142
        }
143
144
//        echo $cacheKey . " " . $this->cache->fetch('[C]'.$cacheKey) . " " . filemtime($filename) . " " . ($this->cache->fetch('[C]'.$cacheKey) >= filemtime($filename)) . "\n";
0 ignored issues
show
Unused Code Comprehensibility introduced by
46% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
145
146
        // When we have the creation time (debug mode) and it is less than the current file time, the cache is also not
147
        // fresh
148
        return $this->cache->fetch('[C]' . $cacheKey) >= filemtime($filename);
149
    }
150
}
151