Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
198 lines (181 sloc) 5.61 KB
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\behaviors;
use yii\base\Behavior;
use yii\base\InvalidConfigException;
use yii\base\Widget;
use yii\base\WidgetEvent;
use yii\caching\CacheInterface;
use yii\caching\Dependency;
use yii\di\Instance;
/**
* Cacheable widget behavior automatically caches widget contents according to duration and dependencies specified.
*
* The behavior may be used without any configuration if an application has `cache` component configured.
* By default the widget will be cached for one minute.
*
* The following example will cache the posts widget for an indefinite duration until any post is modified.
*
* ```php
* use yii\behaviors\CacheableWidgetBehavior;
*
* public function behaviors()
* {
* return [
* [
* 'class' => CacheableWidgetBehavior::className(),
* 'cacheDuration' => 0,
* 'cacheDependency' => [
* 'class' => 'yii\caching\DbDependency',
* 'sql' => 'SELECT MAX(updated_at) FROM posts',
* ],
* ],
* ];
* }
* ```
*
* @author Nikolay Oleynikov <oleynikovny@mail.ru>
* @since 2.0.14
*/
class CacheableWidgetBehavior extends Behavior
{
/**
* @var CacheInterface|string|array a cache object or a cache component ID
* or a configuration array for creating a cache object.
* Defaults to the `cache` application component.
*/
public $cache = 'cache';
/**
* @var int cache duration in seconds.
* Set to `0` to indicate that the cached data will never expire.
* Defaults to 60 seconds or 1 minute.
*/
public $cacheDuration = 60;
/**
* @var Dependency|array|null a cache dependency or a configuration array
* for creating a cache dependency or `null` meaning no cache dependency.
*
* For example,
*
* ```php
* [
* 'class' => 'yii\caching\DbDependency',
* 'sql' => 'SELECT MAX(updated_at) FROM posts',
* ]
* ```
*
* would make the widget cache depend on the last modified time of all posts.
* If any post has its modification time changed, the cached content would be invalidated.
*/
public $cacheDependency;
/**
* @var string[]|string an array of strings or a single string which would cause
* the variation of the content being cached (e.g. an application language, a GET parameter).
*
* The following variation setting will cause the content to be cached in different versions
* according to the current application language:
*
* ```php
* [
* Yii::$app->language,
* ]
* ```
*/
public $cacheKeyVariations = [];
/**
* @var bool whether to enable caching or not. Allows to turn the widget caching
* on and off according to specific conditions.
* The following configuration will disable caching when a special GET parameter is passed:
*
* ```php
* empty(Yii::$app->request->get('disable-caching'))
* ```
*/
public $cacheEnabled = true;
/**
* {@inheritdoc}
*/
public function attach($owner)
{
parent::attach($owner);
$this->initializeEventHandlers();
}
/**
* Begins fragment caching. Prevents owner widget from execution
* if its contents can be retrieved from the cache.
*
* @param WidgetEvent $event `Widget::EVENT_BEFORE_RUN` event.
*/
public function beforeRun($event)
{
$cacheKey = $this->getCacheKey();
$fragmentCacheConfiguration = $this->getFragmentCacheConfiguration();
if (!$this->owner->view->beginCache($cacheKey, $fragmentCacheConfiguration)) {
$event->isValid = false;
}
}
/**
* Outputs widget contents and ends fragment caching.
*
* @param WidgetEvent $event `Widget::EVENT_AFTER_RUN` event.
*/
public function afterRun($event)
{
echo $event->result;
$event->result = null;
$this->owner->view->endCache();
}
/**
* Initializes widget event handlers.
*/
private function initializeEventHandlers()
{
$this->owner->on(Widget::EVENT_BEFORE_RUN, [$this, 'beforeRun']);
$this->owner->on(Widget::EVENT_AFTER_RUN, [$this, 'afterRun']);
}
/**
* Returns the cache instance.
*
* @return CacheInterface cache instance.
* @throws InvalidConfigException if cache instance instantiation fails.
*/
private function getCacheInstance()
{
$cacheInterface = 'yii\caching\CacheInterface';
return Instance::ensure($this->cache, $cacheInterface);
}
/**
* Returns the widget cache key.
*
* @return string[] an array of strings representing the cache key.
*/
private function getCacheKey()
{
// `$cacheKeyVariations` may be a `string` and needs to be cast to an `array`.
$cacheKey = array_merge(
(array)get_class($this->owner),
(array)$this->cacheKeyVariations
);
return $cacheKey;
}
/**
* Returns a fragment cache widget configuration array.
*
* @return array a fragment cache widget configuration array.
*/
private function getFragmentCacheConfiguration()
{
$cache = $this->getCacheInstance();
$fragmentCacheConfiguration = [
'cache' => $cache,
'duration' => $this->cacheDuration,
'dependency' => $this->cacheDependency,
'enabled' => $this->cacheEnabled,
];
return $fragmentCacheConfiguration;
}
}
You can’t perform that action at this time.