Completed
Push — master ( 0b9b86...820e50 )
by Dmitry
48:21 queued 08:27
created

CacheableWidgetBehavior::initializeEventHandlers()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 5
ccs 0
cts 0
cp 0
rs 9.4285
cc 1
eloc 3
nc 1
nop 0
crap 2
1
<?php
2
/**
3
 * @link http://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license http://www.yiiframework.com/license/
6
 */
7
8
namespace yii\behaviors;
9
10
use yii\base\Behavior;
11
use yii\base\InvalidConfigException;
12
use yii\base\Widget;
13
use yii\base\WidgetEvent;
14
use yii\caching\CacheInterface;
15
use yii\caching\Dependency;
16
use yii\di\Instance;
17
18
/**
19
 * Cacheable widget behavior automatically caches widget contents according to duration and dependencies specified.
20
 *
21
 * The behavior may be used without any configuration if an application has `cache` component configured.
22
 * By default the widget will be cached for one minute.
23
 *
24
 * The following example will cache the posts widget for an indefinite duration until any post is modified.
25
 *
26
 * ```php
27
 * use yii\behaviors\CacheableWidgetBehavior;
28
 *
29
 * public function behaviors()
30
 * {
31
 *     return [
32
 *         [
33
 *             'class' => CacheableWidgetBehavior::className(),
34
 *             'cacheDuration' => 0,
35
 *             'cacheDependency' => [
36
 *                 'class' => 'yii\caching\DbDependency',
37
 *                 'sql' => 'SELECT MAX(updated_at) FROM posts',
38
 *             ],
39
 *         ],
40
 *     ];
41
 * }
42
 * ```
43
 *
44
 * @property Widget $owner
45
 *
46
 * @author Nikolay Oleynikov <[email protected]>
47
 * @since 2.0.14
48
 */
49
class CacheableWidgetBehavior extends Behavior
50
{
51
    /**
52
     * @var CacheInterface|string|array a cache object or a cache component ID
53
     * or a configuration array for creating a cache object.
54
     * Defaults to the `cache` application component.
55
     */
56
    public $cache = 'cache';
57
    /**
58
     * @var int cache duration in seconds.
59
     * Set to `0` to indicate that the cached data will never expire.
60
     * Defaults to 60 seconds or 1 minute.
61
     */
62
    public $cacheDuration = 60;
63
    /**
64
     * @var Dependency|array|null a cache dependency or a configuration array
65
     * for creating a cache dependency or `null` meaning no cache dependency.
66
     *
67
     * For example,
68
     *
69
     * ```php
70
     * [
71
     *     'class' => 'yii\caching\DbDependency',
72
     *     'sql' => 'SELECT MAX(updated_at) FROM posts',
73
     * ]
74
     * ```
75
     *
76
     * would make the widget cache depend on the last modified time of all posts.
77
     * If any post has its modification time changed, the cached content would be invalidated.
78
     */
79
    public $cacheDependency;
80
    /**
81
     * @var string[]|string an array of strings or a single string which would cause
82
     * the variation of the content being cached (e.g. an application language, a GET parameter).
83
     *
84
     * The following variation setting will cause the content to be cached in different versions
85
     * according to the current application language:
86
     *
87
     * ```php
88
     * [
89
     *     Yii::$app->language,
90
     * ]
91
     * ```
92
     */
93
    public $cacheKeyVariations = [];
94
    /**
95
     * @var bool whether to enable caching or not. Allows to turn the widget caching
96
     * on and off according to specific conditions.
97
     * The following configuration will disable caching when a special GET parameter is passed:
98
     *
99
     * ```php
100
     * empty(Yii::$app->request->get('disable-caching'))
101
     * ```
102
     */
103
    public $cacheEnabled = true;
104
105
106
    /**
107
     * {@inheritdoc}
108
     */
109
    public function attach($owner)
110
    {
111
        parent::attach($owner);
112
113
        $this->initializeEventHandlers();
114
    }
115
116
    /**
117
     * Begins fragment caching. Prevents owner widget from execution
118
     * if its contents can be retrieved from the cache.
119
     *
120
     * @param WidgetEvent $event `Widget::EVENT_BEFORE_RUN` event.
121
     */
122
    public function beforeRun($event)
123
    {
124
        $cacheKey = $this->getCacheKey();
125
        $fragmentCacheConfiguration = $this->getFragmentCacheConfiguration();
126
127
        if (!$this->owner->view->beginCache($cacheKey, $fragmentCacheConfiguration)) {
0 ignored issues
show
Documentation introduced by
$cacheKey is of type array<integer,string>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
128
            $event->isValid = false;
129
        }
130
    }
131
132
    /**
133
     * Outputs widget contents and ends fragment caching.
134
     *
135
     * @param WidgetEvent $event `Widget::EVENT_AFTER_RUN` event.
136
     */
137
    public function afterRun($event)
138
    {
139
        echo $event->result;
140
        $event->result = null;
141
142
        $this->owner->view->endCache();
143
    }
144
145
    /**
146
     * Initializes widget event handlers.
147
     */
148
    private function initializeEventHandlers()
149
    {
150
        $this->owner->on(Widget::EVENT_BEFORE_RUN, [$this, 'beforeRun']);
151
        $this->owner->on(Widget::EVENT_AFTER_RUN, [$this, 'afterRun']);
152
    }
153
154
    /**
155
     * Returns the cache instance.
156
     *
157
     * @return CacheInterface cache instance.
158
     * @throws InvalidConfigException if cache instance instantiation fails.
159
     */
160
    private function getCacheInstance()
161
    {
162
        $cacheInterface = 'yii\caching\CacheInterface';
163
        return Instance::ensure($this->cache, $cacheInterface);
164
    }
165
166
    /**
167
     * Returns the widget cache key.
168
     *
169
     * @return string[] an array of strings representing the cache key.
170
     */
171
    private function getCacheKey()
172
    {
173
        // `$cacheKeyVariations` may be a `string` and needs to be cast to an `array`.
174
        $cacheKey = array_merge(
175
            (array)get_class($this->owner),
176
            (array)$this->cacheKeyVariations
177
        );
178
179
        return $cacheKey;
180
    }
181
182
    /**
183
     * Returns a fragment cache widget configuration array.
184
     *
185
     * @return array a fragment cache widget configuration array.
186
     */
187
    private function getFragmentCacheConfiguration()
188
    {
189
        $cache = $this->getCacheInstance();
190
        $fragmentCacheConfiguration = [
191
            'cache' => $cache,
192
            'duration' => $this->cacheDuration,
193
            'dependency' => $this->cacheDependency,
194
            'enabled' => $this->cacheEnabled,
195
        ];
196
197
        return $fragmentCacheConfiguration;
198
    }
199
}
200