| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 | <?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;    }}
 |