1 | <?php |
||||||
2 | /** |
||||||
3 | * @link https://www.yiiframework.com/ |
||||||
4 | * @copyright Copyright (c) 2008 Yii Software LLC |
||||||
5 | * @license https://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::class, |
||||||
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 | * @author Nikolay Oleynikov <[email protected]> |
||||||
45 | * @since 2.0.14 |
||||||
46 | */ |
||||||
47 | class CacheableWidgetBehavior extends Behavior |
||||||
48 | { |
||||||
49 | /** |
||||||
50 | * @var CacheInterface|string|array a cache object or a cache component ID |
||||||
51 | * or a configuration array for creating a cache object. |
||||||
52 | * Defaults to the `cache` application component. |
||||||
53 | */ |
||||||
54 | public $cache = 'cache'; |
||||||
55 | /** |
||||||
56 | * @var int cache duration in seconds. |
||||||
57 | * Set to `0` to indicate that the cached data will never expire. |
||||||
58 | * Defaults to 60 seconds or 1 minute. |
||||||
59 | */ |
||||||
60 | public $cacheDuration = 60; |
||||||
61 | /** |
||||||
62 | * @var Dependency|array|null a cache dependency or a configuration array |
||||||
63 | * for creating a cache dependency or `null` meaning no cache dependency. |
||||||
64 | * |
||||||
65 | * For example, |
||||||
66 | * |
||||||
67 | * ```php |
||||||
68 | * [ |
||||||
69 | * 'class' => 'yii\caching\DbDependency', |
||||||
70 | * 'sql' => 'SELECT MAX(updated_at) FROM posts', |
||||||
71 | * ] |
||||||
72 | * ``` |
||||||
73 | * |
||||||
74 | * would make the widget cache depend on the last modified time of all posts. |
||||||
75 | * If any post has its modification time changed, the cached content would be invalidated. |
||||||
76 | */ |
||||||
77 | public $cacheDependency; |
||||||
78 | /** |
||||||
79 | * @var string[]|string an array of strings or a single string which would cause |
||||||
80 | * the variation of the content being cached (e.g. an application language, a GET parameter). |
||||||
81 | * |
||||||
82 | * The following variation setting will cause the content to be cached in different versions |
||||||
83 | * according to the current application language: |
||||||
84 | * |
||||||
85 | * ```php |
||||||
86 | * [ |
||||||
87 | * Yii::$app->language, |
||||||
88 | * ] |
||||||
89 | * ``` |
||||||
90 | */ |
||||||
91 | public $cacheKeyVariations = []; |
||||||
92 | /** |
||||||
93 | * @var bool whether to enable caching or not. Allows to turn the widget caching |
||||||
94 | * on and off according to specific conditions. |
||||||
95 | * The following configuration will disable caching when a special GET parameter is passed: |
||||||
96 | * |
||||||
97 | * ```php |
||||||
98 | * empty(Yii::$app->request->get('disable-caching')) |
||||||
99 | * ``` |
||||||
100 | */ |
||||||
101 | public $cacheEnabled = true; |
||||||
102 | |||||||
103 | |||||||
104 | /** |
||||||
105 | * {@inheritdoc} |
||||||
106 | */ |
||||||
107 | 3 | public function attach($owner) |
|||||
108 | { |
||||||
109 | 3 | parent::attach($owner); |
|||||
110 | |||||||
111 | 3 | $this->initializeEventHandlers(); |
|||||
112 | } |
||||||
113 | |||||||
114 | /** |
||||||
115 | * Begins fragment caching. Prevents owner widget from execution |
||||||
116 | * if its contents can be retrieved from the cache. |
||||||
117 | * |
||||||
118 | * @param WidgetEvent $event `Widget::EVENT_BEFORE_RUN` event. |
||||||
119 | */ |
||||||
120 | 3 | public function beforeRun($event) |
|||||
121 | { |
||||||
122 | 3 | $cacheKey = $this->getCacheKey(); |
|||||
123 | 3 | $fragmentCacheConfiguration = $this->getFragmentCacheConfiguration(); |
|||||
124 | |||||||
125 | 3 | if (!$this->owner->view->beginCache($cacheKey, $fragmentCacheConfiguration)) { |
|||||
0 ignored issues
–
show
Bug
Best Practice
introduced
by
Loading history...
|
|||||||
126 | 2 | $event->isValid = false; |
|||||
127 | } |
||||||
128 | } |
||||||
129 | |||||||
130 | /** |
||||||
131 | * Outputs widget contents and ends fragment caching. |
||||||
132 | * |
||||||
133 | * @param WidgetEvent $event `Widget::EVENT_AFTER_RUN` event. |
||||||
134 | */ |
||||||
135 | 3 | public function afterRun($event) |
|||||
136 | { |
||||||
137 | 3 | echo $event->result; |
|||||
138 | 3 | $event->result = null; |
|||||
139 | |||||||
140 | 3 | $this->owner->view->endCache(); |
|||||
141 | } |
||||||
142 | |||||||
143 | /** |
||||||
144 | * Initializes widget event handlers. |
||||||
145 | */ |
||||||
146 | 3 | private function initializeEventHandlers() |
|||||
147 | { |
||||||
148 | 3 | $this->owner->on(Widget::EVENT_BEFORE_RUN, [$this, 'beforeRun']); |
|||||
0 ignored issues
–
show
The method
on() does not exist on null .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed.
Loading history...
|
|||||||
149 | 3 | $this->owner->on(Widget::EVENT_AFTER_RUN, [$this, 'afterRun']); |
|||||
150 | } |
||||||
151 | |||||||
152 | /** |
||||||
153 | * Returns the cache instance. |
||||||
154 | * |
||||||
155 | * @return CacheInterface cache instance. |
||||||
156 | * @throws InvalidConfigException if cache instance instantiation fails. |
||||||
157 | */ |
||||||
158 | 3 | private function getCacheInstance() |
|||||
159 | { |
||||||
160 | 3 | $cacheInterface = 'yii\caching\CacheInterface'; |
|||||
161 | 3 | return Instance::ensure($this->cache, $cacheInterface); |
|||||
162 | } |
||||||
163 | |||||||
164 | /** |
||||||
165 | * Returns the widget cache key. |
||||||
166 | * |
||||||
167 | * @return string[] an array of strings representing the cache key. |
||||||
168 | */ |
||||||
169 | 3 | private function getCacheKey() |
|||||
170 | { |
||||||
171 | // `$cacheKeyVariations` may be a `string` and needs to be cast to an `array`. |
||||||
172 | 3 | $cacheKey = array_merge( |
|||||
173 | 3 | (array)get_class($this->owner), |
|||||
174 | 3 | (array)$this->cacheKeyVariations |
|||||
175 | 3 | ); |
|||||
176 | |||||||
177 | 3 | return $cacheKey; |
|||||
178 | } |
||||||
179 | |||||||
180 | /** |
||||||
181 | * Returns a fragment cache widget configuration array. |
||||||
182 | * |
||||||
183 | * @return array a fragment cache widget configuration array. |
||||||
184 | */ |
||||||
185 | 3 | private function getFragmentCacheConfiguration() |
|||||
186 | { |
||||||
187 | 3 | $cache = $this->getCacheInstance(); |
|||||
188 | 3 | $fragmentCacheConfiguration = [ |
|||||
189 | 3 | 'cache' => $cache, |
|||||
190 | 3 | 'duration' => $this->cacheDuration, |
|||||
191 | 3 | 'dependency' => $this->cacheDependency, |
|||||
192 | 3 | 'enabled' => $this->cacheEnabled, |
|||||
193 | 3 | ]; |
|||||
194 | |||||||
195 | 3 | return $fragmentCacheConfiguration; |
|||||
196 | } |
||||||
197 | } |
||||||
198 |