Passed
Push — master ( fd18cf...79da56 )
by Evgeniy
02:09
created

Dependency::resetReusableData()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Cache\Dependency;
6
7
use Traversable;
8
use Yiisoft\Cache\CacheInterface;
9
10
use function array_key_exists;
11
use function iterator_to_array;
12
use function serialize;
13
use function sha1;
14
15
/**
16
 * Dependency is the base class for cache dependency classes.
17
 *
18
 * Child classes should override its {@see Dependency::generateDependencyData()}
19
 * for generating the actual dependency data.
20
 */
21
abstract class Dependency
22
{
23
    /**
24
     * @var mixed The dependency data that is saved in cache and later is compared with the latest dependency data.
25
     */
26
    protected $data;
27
28
    /**
29
     * @var bool whether this dependency is reusable or not. True value means that dependent
30
     * data for this cache dependency will be generated only once per request. This allows you
31
     * to use the same cache dependency for multiple separate cache calls while generating the same
32
     * page without an overhead of re-evaluating dependency data each time. Defaults to false.
33
     */
34
    protected bool $isReusable = false;
35
36
    /**
37
     * @var array static storage of cached data for reusable dependencies.
38
     */
39
    private static array $reusableData = [];
40
41
    /**
42
     * Changes dependency behavior so dependent data for this cache dependency will be generated only once per request.
43
     * This allows you to use the same cache dependency for multiple separate cache calls while generating the same
44
     * page without an overhead of re-evaluating dependency data each time.
45
     */
46 3
    public function markAsReusable(): void
47
    {
48 3
        $this->isReusable = true;
49 3
    }
50
51
    /**
52
     * Evaluates the dependency by generating and saving the data related with dependency.
53
     *
54
     * This method is invoked by cache before writing data into it.
55
     *
56
     * @param CacheInterface $cache The cache component that is currently evaluating this dependency.
57
     */
58 26
    public function evaluateDependency(CacheInterface $cache): void
59
    {
60 26
        if (!$this->isReusable) {
61 24
            $this->data = $this->generateDependencyData($cache);
62 23
            return;
63
        }
64
65 2
        $hash = $this->generateReusableHash();
66
67 2
        if (!array_key_exists($hash, self::$reusableData)) {
68 2
            self::$reusableData[$hash] = $this->generateDependencyData($cache);
69
        }
70
71 2
        $this->data = self::$reusableData[$hash];
72 2
    }
73
74
    /**
75
     * Checks whether the dependency is changed.
76
     *
77
     * @param CacheInterface $cache The cache component that is currently evaluating this dependency
78
     *
79
     * @return bool Whether the dependency has changed.
80
     */
81 17
    public function isChanged(CacheInterface $cache): bool
82
    {
83 17
        if (!$this->isReusable) {
84 15
            return $this->data !== $this->generateDependencyData($cache);
85
        }
86
87 2
        $hash = $this->generateReusableHash();
88
89 2
        if (!array_key_exists($hash, self::$reusableData)) {
90 1
            self::$reusableData[$hash] = $this->generateDependencyData($cache);
91
        }
92
93 2
        return $this->data !== self::$reusableData[$hash];
94
    }
95
96
    /**
97
     * Resets all cached data for reusable dependencies.
98
     */
99 1
    public static function resetReusableData(): void
100
    {
101 1
        self::$reusableData = [];
102 1
    }
103
104
    /**
105
     * Generates a unique hash that can be used for retrieving reusable dependency data.
106
     *
107
     * @return string a unique hash value for this cache dependency.
108
     *
109
     * @see isReusable()
110
     */
111 4
    protected function generateReusableHash(): string
112
    {
113 4
        $data = $this->data;
114 4
        $this->data = null; // https://github.com/yiisoft/yii2/issues/3052
115 4
        $key = sha1(serialize($this));
116 4
        $this->data = $data;
117 4
        return $key;
118
    }
119
120
    /**
121
     * Converts iterable to array
122
     *
123
     * @param iterable $iterable
124
     *
125
     * @return array
126
     */
127 15
    protected function iterableToArray(iterable $iterable): array
128
    {
129
        /** @psalm-suppress RedundantCast */
130 15
        return $iterable instanceof Traversable ? iterator_to_array($iterable) : (array) $iterable;
131
    }
132
133
    /**
134
     * Generates the data needed to determine if dependency is changed.
135
     *
136
     * Derived classes should override this method to generate the actual dependency data.
137
     *
138
     * @param CacheInterface $cache The cache component that is currently evaluating this dependency
139
     *
140
     * @return mixed The data needed to determine if dependency has been changed.
141
     */
142
    abstract protected function generateDependencyData(CacheInterface $cache);
143
}
144