CacheBehavior::setCache()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 9
rs 9.9666
cc 3
nc 2
nop 3
1
<?php
2
/**
3
 * @author Brett O'Donnell <[email protected]>
4
 * @copyright 2016 Mr PHP
5
 * @link https://github.com/cornernote/yii2-cache-behavior
6
 * @license BSD-3-Clause https://raw.github.com/cornernote/yii2-cache-behavior/master/LICENSE.md
7
 */
8
9
namespace cornernote\cachebehavior;
10
11
use Yii;
12
use yii\base\Behavior;
13
use yii\base\Event;
14
use yii\db\BaseActiveRecord;
15
16
/**
17
 * CacheBehavior
18
 *
19
 * @usage:
20
 * ```
21
 * public function behaviors() {
22
 *     return [
23
 *         [
24
 *             'class' => 'cornernote\cachebehavior\CacheBehavior',
25
 *         ],
26
 *     ];
27
 * }
28
 * ```
29
 *
30
 * @property BaseActiveRecord $owner
31
 * @property string $cacheKeyPrefixName
32
 *
33
 */
34
class CacheBehavior extends Behavior
35
{
36
    /**
37
     * The cache component to use.
38
     *
39
     * @var string
40
     */
41
    public $cache = 'cache';
42
43
    /**
44
     * A backup cache component to use.
45
     * For example if your main cache is MemCache then you may want to use
46
     * FileCache or DbCache as a backup cache storage.
47
     *
48
     * @var bool
49
     */
50
    public $backupCache = false;
51
52
    /**
53
     * The relations to clear cache when this models cache is cleared.
54
     *
55
     * @var array
56
     */
57
    public $cacheRelations = [];
58
59
    /**
60
     * Unique md5 for this model.
61
     *
62
     * @var string
63
     */
64
    protected $_cacheKeyPrefixName;
65
66
    /**
67
     * Keys that have already been cleared.
68
     *
69
     * @var array
70
     */
71
    protected $_cacheKeysCleared = [];
72
73
    /**
74
     * @inheritdoc
75
     */
76
    public function events()
77
    {
78
        return [
79
            BaseActiveRecord::EVENT_AFTER_INSERT => 'clearCacheEvent',
80
            BaseActiveRecord::EVENT_AFTER_UPDATE => 'clearCacheEvent',
81
            BaseActiveRecord::EVENT_AFTER_DELETE => 'clearCacheEvent',
82
        ];
83
    }
84
85
    /**
86
     * Event to clear cache.
87
     *
88
     * @param Event $event
89
     */
90
    public function clearCacheEvent($event)
0 ignored issues
show
Unused Code introduced by
The parameter $event is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
91
    {
92
        $this->clearCache();
93
    }
94
95
    /**
96
     * Get a cached value.
97
     *
98
     * @param string $key
99
     * @param bool $useBackupCache
100
     * @return mixed
101
     */
102
    public function getCache($key, $useBackupCache = false)
103
    {
104
        $fullKey = $this->getCacheKeyPrefix() . '.' . $key;
105
        $value = Yii::$app->{$this->cache}->get($fullKey);
106
        if (!$value && $useBackupCache && $this->backupCache) {
107
            $value = Yii::$app->{$this->backupCache}->get($fullKey);
108
            if ($value !== false) {
109
                Yii::$app->{$this->cache}->set($fullKey, $value);
110
            }
111
        }
112
        return $value;
113
    }
114
115
    /**
116
     * Set a cached value.
117
     *
118
     * @param string $key
119
     * @param mixed $value
120
     * @param bool $useBackupCache
121
     * @return mixed
122
     */
123
    public function setCache($key, $value, $useBackupCache = false)
124
    {
125
        $fullKey = $this->getCacheKeyPrefix() . '.' . $key;
126
        Yii::$app->{$this->cache}->set($fullKey, $value);
127
        if ($useBackupCache && $this->backupCache) {
128
            Yii::$app->{$this->backupCache}->set($fullKey, $value);
129
        }
130
        return $value;
131
    }
132
133
    /**
134
     * Clear cache for model and relations.
135
     *
136
     * @param bool $resetCleared
137
     */
138
    public function clearCache($resetCleared = true)
139
    {
140
        // check for recursion
141
        if ($resetCleared) {
142
            $this->_cacheKeysCleared = [];
143
        }
144
        if (isset($this->_cacheKeysCleared[$this->cacheKeyPrefixName])) {
145
            return;
146
        }
147
        $this->_cacheKeysCleared[$this->cacheKeyPrefixName] = true;
148
        // clear related cache
149
        foreach ($this->cacheRelations as $cacheRelation) {
150
            $models = is_array($this->owner->$cacheRelation) ? $this->owner->$cacheRelation : [$this->owner->$cacheRelation];
151
            foreach ($models as $cacheRelationModel) {
152
                if ($cacheRelationModel instanceof BaseActiveRecord) {
153
                    $cacheRelationModel->clearCache(false);
154
                }
155
            }
156
        }
157
        // clear own cache
158
        $this->clearCacheKeyPrefix();
159
    }
160
161
    /**
162
     * Get the cache prefix.
163
     *
164
     * @return bool|string
165
     */
166
    public function getCacheKeyPrefix()
167
    {
168
        $cacheKeyPrefix = Yii::$app->{$this->cache}->get($this->cacheKeyPrefixName);
169
        if (!$cacheKeyPrefix && $this->backupCache) {
170
            $cacheKeyPrefix = Yii::$app->{$this->backupCache}->get($this->cacheKeyPrefixName);
171
        }
172
        if (!$cacheKeyPrefix) {
173
            $cacheKeyPrefix = $this->setCacheKeyPrefix();
174
        }
175
        return $cacheKeyPrefix;
176
    }
177
178
    /**
179
     * Set the cache prefix.
180
     *
181
     * @param null|string $cacheKeyPrefix
182
     */
183
    public function setCacheKeyPrefix($cacheKeyPrefix = null)
184
    {
185
        if (!$cacheKeyPrefix) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $cacheKeyPrefix of type null|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
186
            $cacheKeyPrefix = md5($this->cacheKeyPrefixName . '.' . bin2hex(openssl_random_pseudo_bytes(10)));
187
        }
188
        Yii::$app->{$this->cache}->set($this->cacheKeyPrefixName, $cacheKeyPrefix);
189
        if ($this->backupCache) {
190
            Yii::$app->{$this->backupCache}->set($this->cacheKeyPrefixName, $cacheKeyPrefix);
191
        }
192
        return $cacheKeyPrefix;
193
    }
194
195
196
    /**
197
     * Clear the cache prefix.
198
     *
199
     * @param null|string $cacheKeyPrefix
0 ignored issues
show
Bug introduced by
There is no parameter named $cacheKeyPrefix. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
200
     */
201
    protected function clearCacheKeyPrefix()
202
    {
203
        Yii::$app->{$this->cache}->delete($this->cacheKeyPrefixName);
204
        if ($this->backupCache) {
205
            Yii::$app->{$this->backupCache}->delete($this->cacheKeyPrefixName);
206
        }
207
    }
208
209
    /**
210
     * Get the cache prefix name.
211
     *
212
     * @return string
213
     */
214
    public function getCacheKeyPrefixName()
215
    {
216
        if (!$this->_cacheKeyPrefixName) {
217
            $owner = $this->owner;
218
            $pk = is_array($owner->getPrimaryKey()) ? implode('-', $owner->getPrimaryKey()) : $owner->getPrimaryKey();
219
            $this->_cacheKeyPrefixName = md5($owner->className() . '.getCacheKeyPrefixName.' . $pk);
220
        }
221
        return $this->_cacheKeyPrefixName;
222
    }
223
224
}
225