Completed
Push — master ( 089685...22832b )
by Dmitry
25:22 queued 11:13
created

CacheableWidgetBehavior::afterRun()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 7
ccs 5
cts 5
cp 1
rs 9.4285
cc 1
eloc 4
nc 1
nop 1
crap 1
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
class CacheableWidgetBehavior extends Behavior
45
{
46
    /**
47
     * @var CacheInterface|string|array a cache object or a cache component ID
48
     * or a configuration array for creating a cache object.
49
     * Defaults to the `cache` application component.
50
     */
51
    public $cache = 'cache';
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected T_PUBLIC
Loading history...
52
    /**
53
     * @var int cache duration in seconds.
54
     * Set to `0` to indicate that the cached data will never expire.
55
     * Defaults to 60 seconds or 1 minute.
56
     */
57
    public $cacheDuration = 60;
58
    /**
59
     * @var Dependency|array|null a cache dependency or a configuration array
60
     * for creating a cache dependency or `null` meaning no cache dependency.
61
     *
62
     * For example,
63
     *
64
     * ```php
65
     * [
66
     *     'class' => 'yii\caching\DbDependency',
67
     *     'sql' => 'SELECT MAX(updated_at) FROM posts',
68
     * ]
69
     * ```
70
     *
71
     * would make the widget cache depend on the last modified time of all posts.
72
     * If any post has its modification time changed, the cached content would be invalidated.
73
     */
74
    public $cacheDependency;
75
    /**
76
     * @var string[]|string an array of strings or a single string which would cause
77
     * the variation of the content being cached (e.g. an application language, a GET parameter).
78
     *
79
     * The following variation setting will cause the content to be cached in different versions
80
     * according to the current application language:
81
     *
82
     * ```php
83
     * [
84
     *     Yii::$app->language,
85
     * ]
86
     * ```
87
     */
88
    public $cacheKeyVariations = [];
89
    /**
90
     * @var bool whether to enable caching or not. Allows to turn the widget caching
91
     * on and off according to specific conditions.
92
     * The following configuration will disable caching when a special GET parameter is passed:
93
     *
94
     * ```php
95
     * empty(Yii::$app->request->get('disable-caching'))
96
     * ```
97
     */
98
    public $cacheEnabled = true;
99
100
101
    /**
102
     * {@inheritdoc}
103
     */
104
    public function attach($owner)
105
    {
106
        parent::attach($owner);
107
108
        $this->initializeEventHandlers();
109
    }
110
111
    /**
112
     * Begins fragment caching. Prevents owner widget from execution
113
     * if its contents can be retrieved from the cache.
114
     *
115
     * @param WidgetEvent $event `Widget::EVENT_BEFORE_RUN` event.
116
     */
117
    public function beforeRun($event)
118
    {
119
        $cacheKey = $this->getCacheKey();
120
        $fragmentCacheConfiguration = $this->getFragmentCacheConfiguration();
121
122
        if (!$this->owner->view->beginCache($cacheKey, $fragmentCacheConfiguration)) {
123
            $event->isValid = false;
124
        }
125
    }
126
127
    /**
128
     * Outputs widget contents and ends fragment caching.
129
     *
130
     * @param WidgetEvent $event `Widget::EVENT_AFTER_RUN` event.
131
     */
132
    public function afterRun($event)
133
    {
134
        echo $event->result;
135
        $event->result = null;
136
137
        $this->owner->view->endCache();
138
    }
139
140
    /**
141
     * Initializes widget event handlers.
142
     */
143
    private function initializeEventHandlers()
144
    {
145
        $this->owner->on(Widget::EVENT_BEFORE_RUN, [$this, 'beforeRun']);
146
        $this->owner->on(Widget::EVENT_AFTER_RUN, [$this, 'afterRun']);
147
    }
148
149
    /**
150
     * Returns the cache instance.
151
     *
152
     * @return CacheInterface cache instance.
153
     * @throws InvalidConfigException if cache instance instantiation fails.
154
     */
155
    private function getCacheInstance()
156
    {
157
        $cacheInterface = 'yii\caching\CacheInterface';
158
        return Instance::ensure($this->cache, $cacheInterface);
159
    }
160
161
    /**
162
     * Returns the widget cache key.
163
     *
164
     * @return string[] an array of strings representing the cache key.
165
     */
166
    private function getCacheKey()
167
    {
168
        // `$cacheKeyVariations` may be a `string` and needs to be cast to an `array`.
169
        $cacheKey = array_merge(
170
            (array)get_class($this->owner),
171
            (array)$this->cacheKeyVariations
172
        );
173
174
        return $cacheKey;
175
    }
176
177
    /**
178
     * Returns a fragment cache widget configuration array.
179
     *
180
     * @return array a fragment cache widget configuration array.
181
     */
182
    private function getFragmentCacheConfiguration()
183
    {
184
        $cache = $this->getCacheInstance();
185
        $fragmentCacheConfiguration = [
186
            'cache' => $cache,
187
            'duration' => $this->cacheDuration,
188
            'dependency' => $this->cacheDependency,
189
            'enabled' => $this->cacheEnabled,
190
        ];
191
192
        return $fragmentCacheConfiguration;
193
    }
194
}
195