mirror of
https://github.com/yiisoft/yii2.git
synced 2025-08-26 14:26:54 +08:00
Fixes #15120: Refactored dynamic caching introducing DynamicContentAwareInterface
and DynamicContentAwareTrait
This commit is contained in:

committed by
Alexander Makarov

parent
1cd4bb8ac8
commit
c382d3e8d4
@ -174,3 +174,6 @@ if ($this->beginCache($id1)) {
|
|||||||
The [[yii\base\View::renderDynamic()|renderDynamic()]] method takes a piece of PHP code as its parameter.
|
The [[yii\base\View::renderDynamic()|renderDynamic()]] method takes a piece of PHP code as its parameter.
|
||||||
The return value of the PHP code is treated as the dynamic content. The same PHP code will be executed
|
The return value of the PHP code is treated as the dynamic content. The same PHP code will be executed
|
||||||
for every request, no matter the enclosing fragment is being served from cached or not.
|
for every request, no matter the enclosing fragment is being served from cached or not.
|
||||||
|
|
||||||
|
> Note: since version 2.0.14 a dynamic content API is exposed via the [[yii\base\DynamicContentAwareInterface]] interface and its [[yii\base\DynamicContentAwareTrait]] trait.
|
||||||
|
As an example, you may refer to the [[yii\widgets\FragmentCache]] class.
|
||||||
|
@ -4,6 +4,7 @@ Yii Framework 2 Change Log
|
|||||||
2.0.14 under development
|
2.0.14 under development
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
|
- Enh #15120: Refactored dynamic caching introducing `DynamicContentAwareInterface` and `DynamicContentAwareTrait` (sergeymakinen)
|
||||||
- Bug #8983: Only truncate the original log file for rotation (matthewyang, developeruz)
|
- Bug #8983: Only truncate the original log file for rotation (matthewyang, developeruz)
|
||||||
- Bug #11401: Fixed `yii\web\DbSession` concurrency issues when writing and regenerating IDs (samdark, andreasanta, cebe)
|
- Bug #11401: Fixed `yii\web\DbSession` concurrency issues when writing and regenerating IDs (samdark, andreasanta, cebe)
|
||||||
- Bug #13034: Fixed `normalizePath` for windows network shares that start with two backslashes (developeruz)
|
- Bug #13034: Fixed `normalizePath` for windows network shares that start with two backslashes (developeruz)
|
||||||
|
40
framework/base/DynamicContentAwareInterface.php
Normal file
40
framework/base/DynamicContentAwareInterface.php
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @link http://www.yiiframework.com/
|
||||||
|
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||||
|
* @license http://www.yiiframework.com/license/
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace yii\base;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DynamicContentAwareInterface is the interface that should be implemented by classes
|
||||||
|
* which support a [[View]] dynamic content feature.
|
||||||
|
*
|
||||||
|
* @author Sergey Makinen <sergey@makinen.ru>
|
||||||
|
* @since 2.0.14
|
||||||
|
*/
|
||||||
|
interface DynamicContentAwareInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns a list of placeholders for dynamic content. This method
|
||||||
|
* is used internally to implement the content caching feature.
|
||||||
|
* @return array a list of placeholders.
|
||||||
|
*/
|
||||||
|
public function getDynamicPlaceholders();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a list of placeholders for dynamic content. This method
|
||||||
|
* is used internally to implement the content caching feature.
|
||||||
|
* @param array $placeholders a list of placeholders.
|
||||||
|
*/
|
||||||
|
public function setDynamicPlaceholders($placeholders);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a placeholder for dynamic content.
|
||||||
|
* This method is used internally to implement the content caching feature.
|
||||||
|
* @param string $name the placeholder name.
|
||||||
|
* @param string $statements the PHP statements for generating the dynamic content.
|
||||||
|
*/
|
||||||
|
public function addDynamicPlaceholder($name, $statements);
|
||||||
|
}
|
77
framework/base/DynamicContentAwareTrait.php
Normal file
77
framework/base/DynamicContentAwareTrait.php
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace yii\base;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DynamicContentAwareTrait implements common methods for classes
|
||||||
|
* which support a [[View]] dynamic content feature.
|
||||||
|
*
|
||||||
|
* @author Sergey Makinen <sergey@makinen.ru>
|
||||||
|
* @since 2.0.14
|
||||||
|
*/
|
||||||
|
trait DynamicContentAwareTrait
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string[] a list of placeholders for dynamic content
|
||||||
|
*/
|
||||||
|
private $_dynamicPlaceholders;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the view object that can be used to render views or view files using dynamic contents.
|
||||||
|
* @return View the view object that can be used to render views or view files.
|
||||||
|
*/
|
||||||
|
abstract protected function getView();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getDynamicPlaceholders()
|
||||||
|
{
|
||||||
|
return $this->_dynamicPlaceholders;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function setDynamicPlaceholders($placeholders)
|
||||||
|
{
|
||||||
|
$this->_dynamicPlaceholders = $placeholders;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function addDynamicPlaceholder($name, $statements)
|
||||||
|
{
|
||||||
|
$this->_dynamicPlaceholders[$name] = $statements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces placeholders in $content with results of evaluated dynamic statements.
|
||||||
|
* @param string $content content to be parsed.
|
||||||
|
* @param string[] $placeholders placeholders and their values.
|
||||||
|
* @param bool $isRestoredFromCache whether content is going to be restored from cache.
|
||||||
|
* @return string final content.
|
||||||
|
*/
|
||||||
|
protected function updateDynamicContent($content, $placeholders, $isRestoredFromCache = false)
|
||||||
|
{
|
||||||
|
if (empty($placeholders) || !is_array($placeholders)) {
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($this->getView()->getDynamicContents()) === 0) {
|
||||||
|
// outermost cache: replace placeholder with dynamic content
|
||||||
|
foreach ($placeholders as $name => $statements) {
|
||||||
|
$placeholders[$name] = $this->getView()->evaluateDynamicContent($statements);
|
||||||
|
}
|
||||||
|
$content = strtr($content, $placeholders);
|
||||||
|
}
|
||||||
|
if ($isRestoredFromCache) {
|
||||||
|
foreach ($placeholders as $name => $statements) {
|
||||||
|
$this->getView()->addDynamicPlaceholder($name, $statements);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
}
|
@ -26,7 +26,7 @@ use yii\widgets\FragmentCache;
|
|||||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
*/
|
*/
|
||||||
class View extends Component
|
class View extends Component implements DynamicContentAwareInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @event Event an event that is triggered by [[beginPage()]].
|
* @event Event an event that is triggered by [[beginPage()]].
|
||||||
@ -86,15 +86,19 @@ class View extends Component
|
|||||||
*/
|
*/
|
||||||
public $blocks;
|
public $blocks;
|
||||||
/**
|
/**
|
||||||
* @var array a list of currently active fragment cache widgets. This property
|
* @var array|DynamicContentAwareInterface[] a list of currently active dynamic content class instances.
|
||||||
* is used internally to implement the content caching feature. Do not modify it directly.
|
* This property is used internally to implement the dynamic content caching feature. Do not modify it directly.
|
||||||
* @internal
|
* @internal
|
||||||
|
* @deprecated Sice 2.0.14. Do not use this property directly. Use methods [[getDynamicContents()]],
|
||||||
|
* [[pushDynamicContent()]], [[popDynamicContent()]] instead.
|
||||||
*/
|
*/
|
||||||
public $cacheStack = [];
|
public $cacheStack = [];
|
||||||
/**
|
/**
|
||||||
* @var array a list of placeholders for embedding dynamic contents. This property
|
* @var array a list of placeholders for embedding dynamic contents. This property
|
||||||
* is used internally to implement the content caching feature. Do not modify it directly.
|
* is used internally to implement the content caching feature. Do not modify it directly.
|
||||||
* @internal
|
* @internal
|
||||||
|
* @deprecated Since 2.0.14. Do not use this property directly. Use methods [[getDynamicPlaceholders()]],
|
||||||
|
* [[setDynamicPlaceholders()]], [[addDynamicPlaceholder()]] instead.
|
||||||
*/
|
*/
|
||||||
public $dynamicPlaceholders = [];
|
public $dynamicPlaceholders = [];
|
||||||
|
|
||||||
@ -371,18 +375,36 @@ class View extends Component
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a placeholder for dynamic content.
|
* {@inheritdoc}
|
||||||
* This method is internally used.
|
*/
|
||||||
* @param string $placeholder the placeholder name
|
public function getDynamicPlaceholders()
|
||||||
* @param string $statements the PHP statements for generating the dynamic content
|
{
|
||||||
|
return $this->dynamicPlaceholders;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function setDynamicPlaceholders($placeholders)
|
||||||
|
{
|
||||||
|
$this->dynamicPlaceholders = $placeholders;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function addDynamicPlaceholder($placeholder, $statements)
|
public function addDynamicPlaceholder($placeholder, $statements)
|
||||||
{
|
{
|
||||||
foreach ($this->cacheStack as $cache) {
|
foreach ($this->cacheStack as $cache) {
|
||||||
$cache->dynamicPlaceholders[$placeholder] = $statements;
|
if ($cache instanceof DynamicContentAwareInterface) {
|
||||||
|
$cache->addDynamicPlaceholder($placeholder, $statements);
|
||||||
|
} else {
|
||||||
|
// To be removed in 2.1
|
||||||
|
$cache->dynamicPlaceholders[$placeholder] = $statements;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$this->dynamicPlaceholders[$placeholder] = $statements;
|
$this->dynamicPlaceholders[$placeholder] = $statements;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluates the given PHP statements.
|
* Evaluates the given PHP statements.
|
||||||
@ -395,6 +417,37 @@ class View extends Component
|
|||||||
return eval($statements);
|
return eval($statements);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of currently active dynamic content class instances.
|
||||||
|
* @return DynamicContentAwareInterface[] class instances supporting dynamic contents.
|
||||||
|
* @since 2.0.14
|
||||||
|
*/
|
||||||
|
public function getDynamicContents()
|
||||||
|
{
|
||||||
|
return $this->cacheStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a class instance supporting dynamic contents to the end of a list of currently active
|
||||||
|
* dynamic content class instances.
|
||||||
|
* @param DynamicContentAwareInterface $instance class instance supporting dynamic contents.
|
||||||
|
* @since 2.0.14
|
||||||
|
*/
|
||||||
|
public function pushDynamicContent(DynamicContentAwareInterface $instance)
|
||||||
|
{
|
||||||
|
$this->cacheStack[] = $instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a last class instance supporting dynamic contents from a list of currently active
|
||||||
|
* dynamic content class instances.
|
||||||
|
* @since 2.0.14
|
||||||
|
*/
|
||||||
|
public function popDynamicContent()
|
||||||
|
{
|
||||||
|
array_pop($this->cacheStack);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Begins recording a block.
|
* Begins recording a block.
|
||||||
*
|
*
|
||||||
|
@ -10,6 +10,8 @@ namespace yii\filters;
|
|||||||
use Yii;
|
use Yii;
|
||||||
use yii\base\Action;
|
use yii\base\Action;
|
||||||
use yii\base\ActionFilter;
|
use yii\base\ActionFilter;
|
||||||
|
use yii\base\DynamicContentAwareInterface;
|
||||||
|
use yii\base\DynamicContentAwareTrait;
|
||||||
use yii\caching\CacheInterface;
|
use yii\caching\CacheInterface;
|
||||||
use yii\caching\Dependency;
|
use yii\caching\Dependency;
|
||||||
use yii\di\Instance;
|
use yii\di\Instance;
|
||||||
@ -49,8 +51,16 @@ use yii\web\Response;
|
|||||||
* @author Sergey Makinen <sergey@makinen.ru>
|
* @author Sergey Makinen <sergey@makinen.ru>
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
*/
|
*/
|
||||||
class PageCache extends ActionFilter
|
class PageCache extends ActionFilter implements DynamicContentAwareInterface
|
||||||
{
|
{
|
||||||
|
use DynamicContentAwareTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page cache version, to detect incompatibilities in cached values when the
|
||||||
|
* data format of the cache changes.
|
||||||
|
*/
|
||||||
|
const PAGE_CACHE_VERSION = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var bool whether the content being cached should be differentiated according to the route.
|
* @var bool whether the content being cached should be differentiated according to the route.
|
||||||
* A route consists of the requested controller ID and action ID. Defaults to `true`.
|
* A route consists of the requested controller ID and action ID. Defaults to `true`.
|
||||||
@ -124,13 +134,6 @@ class PageCache extends ActionFilter
|
|||||||
* @since 2.0.4
|
* @since 2.0.4
|
||||||
*/
|
*/
|
||||||
public $cacheHeaders = true;
|
public $cacheHeaders = true;
|
||||||
/**
|
|
||||||
* @var array a list of placeholders for embedding dynamic contents. This property
|
|
||||||
* is used internally to implement the content caching feature. Do not modify it.
|
|
||||||
* @internal
|
|
||||||
* @since 2.0.11
|
|
||||||
*/
|
|
||||||
public $dynamicPlaceholders;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -164,8 +167,8 @@ class PageCache extends ActionFilter
|
|||||||
|
|
||||||
$response = Yii::$app->getResponse();
|
$response = Yii::$app->getResponse();
|
||||||
$data = $this->cache->get($this->calculateCacheKey());
|
$data = $this->cache->get($this->calculateCacheKey());
|
||||||
if (!is_array($data) || !isset($data['cacheVersion']) || $data['cacheVersion'] !== 1) {
|
if (!is_array($data) || !isset($data['cacheVersion']) || $data['cacheVersion'] !== static::PAGE_CACHE_VERSION) {
|
||||||
$this->view->cacheStack[] = $this;
|
$this->view->pushDynamicContent($this);
|
||||||
ob_start();
|
ob_start();
|
||||||
ob_implicit_flush(false);
|
ob_implicit_flush(false);
|
||||||
$response->on(Response::EVENT_AFTER_SEND, [$this, 'cacheResponse']);
|
$response->on(Response::EVENT_AFTER_SEND, [$this, 'cacheResponse']);
|
||||||
@ -217,13 +220,7 @@ class PageCache extends ActionFilter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!empty($data['dynamicPlaceholders']) && is_array($data['dynamicPlaceholders'])) {
|
if (!empty($data['dynamicPlaceholders']) && is_array($data['dynamicPlaceholders'])) {
|
||||||
if (empty($this->view->cacheStack)) {
|
$response->content = $this->updateDynamicContent($response->content, $data['dynamicPlaceholders'], true);
|
||||||
// outermost cache: replace placeholder with dynamic content
|
|
||||||
$response->content = $this->updateDynamicContent($response->content, $data['dynamicPlaceholders']);
|
|
||||||
}
|
|
||||||
foreach ($data['dynamicPlaceholders'] as $name => $statements) {
|
|
||||||
$this->view->addDynamicPlaceholder($name, $statements);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
$this->afterRestoreResponse(isset($data['cacheData']) ? $data['cacheData'] : null);
|
$this->afterRestoreResponse(isset($data['cacheData']) ? $data['cacheData'] : null);
|
||||||
}
|
}
|
||||||
@ -234,20 +231,16 @@ class PageCache extends ActionFilter
|
|||||||
*/
|
*/
|
||||||
public function cacheResponse()
|
public function cacheResponse()
|
||||||
{
|
{
|
||||||
array_pop($this->view->cacheStack);
|
$this->view->popDynamicContent();
|
||||||
$beforeCacheResponseResult = $this->beforeCacheResponse();
|
$beforeCacheResponseResult = $this->beforeCacheResponse();
|
||||||
if ($beforeCacheResponseResult === false) {
|
if ($beforeCacheResponseResult === false) {
|
||||||
$content = ob_get_clean();
|
echo $this->updateDynamicContent(ob_get_clean(), $this->getDynamicPlaceholders());
|
||||||
if (empty($this->view->cacheStack) && !empty($this->dynamicPlaceholders)) {
|
|
||||||
$content = $this->updateDynamicContent($content, $this->dynamicPlaceholders);
|
|
||||||
}
|
|
||||||
echo $content;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$response = Yii::$app->getResponse();
|
$response = Yii::$app->getResponse();
|
||||||
$data = [
|
$data = [
|
||||||
'cacheVersion' => 1,
|
'cacheVersion' => static::PAGE_CACHE_VERSION,
|
||||||
'cacheData' => is_array($beforeCacheResponseResult) ? $beforeCacheResponseResult : null,
|
'cacheData' => is_array($beforeCacheResponseResult) ? $beforeCacheResponseResult : null,
|
||||||
'content' => ob_get_clean(),
|
'content' => ob_get_clean(),
|
||||||
];
|
];
|
||||||
@ -255,16 +248,14 @@ class PageCache extends ActionFilter
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$data['dynamicPlaceholders'] = $this->dynamicPlaceholders;
|
$data['dynamicPlaceholders'] = $this->getDynamicPlaceholders();
|
||||||
foreach (['format', 'version', 'statusCode', 'statusText'] as $name) {
|
foreach (['format', 'version', 'statusCode', 'statusText'] as $name) {
|
||||||
$data[$name] = $response->{$name};
|
$data[$name] = $response->{$name};
|
||||||
}
|
}
|
||||||
$this->insertResponseCollectionIntoData($response, 'headers', $data);
|
$this->insertResponseCollectionIntoData($response, 'headers', $data);
|
||||||
$this->insertResponseCollectionIntoData($response, 'cookies', $data);
|
$this->insertResponseCollectionIntoData($response, 'cookies', $data);
|
||||||
$this->cache->set($this->calculateCacheKey(), $data, $this->duration, $this->dependency);
|
$this->cache->set($this->calculateCacheKey(), $data, $this->duration, $this->dependency);
|
||||||
if (empty($this->view->cacheStack) && !empty($this->dynamicPlaceholders)) {
|
$data['content'] = $this->updateDynamicContent($data['content'], $this->getDynamicPlaceholders());
|
||||||
$data['content'] = $this->updateDynamicContent($data['content'], $this->dynamicPlaceholders);
|
|
||||||
}
|
|
||||||
echo $data['content'];
|
echo $data['content'];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,22 +288,6 @@ class PageCache extends ActionFilter
|
|||||||
$data[$collectionName] = $all;
|
$data[$collectionName] = $all;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Replaces placeholders in content by results of evaluated dynamic statements.
|
|
||||||
* @param string $content content to be parsed.
|
|
||||||
* @param array $placeholders placeholders and their values.
|
|
||||||
* @return string final content.
|
|
||||||
* @since 2.0.11
|
|
||||||
*/
|
|
||||||
protected function updateDynamicContent($content, $placeholders)
|
|
||||||
{
|
|
||||||
foreach ($placeholders as $name => $statements) {
|
|
||||||
$placeholders[$name] = $this->view->evaluateDynamicContent($statements);
|
|
||||||
}
|
|
||||||
|
|
||||||
return strtr($content, $placeholders);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array the key used to cache response properties.
|
* @return array the key used to cache response properties.
|
||||||
* @since 2.0.3
|
* @since 2.0.3
|
||||||
@ -325,4 +300,12 @@ class PageCache extends ActionFilter
|
|||||||
}
|
}
|
||||||
return array_merge($key, (array)$this->variations);
|
return array_merge($key, (array)$this->variations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected function getView()
|
||||||
|
{
|
||||||
|
return $this->view;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
namespace yii\widgets;
|
namespace yii\widgets;
|
||||||
|
|
||||||
use Yii;
|
use Yii;
|
||||||
|
use yii\base\DynamicContentAwareInterface;
|
||||||
|
use yii\base\DynamicContentAwareTrait;
|
||||||
use yii\base\Widget;
|
use yii\base\Widget;
|
||||||
use yii\caching\CacheInterface;
|
use yii\caching\CacheInterface;
|
||||||
use yii\caching\Dependency;
|
use yii\caching\Dependency;
|
||||||
@ -22,8 +24,10 @@ use yii\di\Instance;
|
|||||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
*/
|
*/
|
||||||
class FragmentCache extends Widget
|
class FragmentCache extends Widget implements DynamicContentAwareInterface
|
||||||
{
|
{
|
||||||
|
use DynamicContentAwareTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var CacheInterface|array|string the cache object or the application component ID of the cache object.
|
* @var CacheInterface|array|string the cache object or the application component ID of the cache object.
|
||||||
* After the FragmentCache object is created, if you want to change this property,
|
* After the FragmentCache object is created, if you want to change this property,
|
||||||
@ -70,11 +74,6 @@ class FragmentCache extends Widget
|
|||||||
* the fragment cache according to specific setting (e.g. enable fragment cache only for GET requests).
|
* the fragment cache according to specific setting (e.g. enable fragment cache only for GET requests).
|
||||||
*/
|
*/
|
||||||
public $enabled = true;
|
public $enabled = true;
|
||||||
/**
|
|
||||||
* @var array a list of placeholders for embedding dynamic contents. This property
|
|
||||||
* is used internally to implement the content caching feature. Do not modify it.
|
|
||||||
*/
|
|
||||||
public $dynamicPlaceholders;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -87,7 +86,7 @@ class FragmentCache extends Widget
|
|||||||
$this->cache = $this->enabled ? Instance::ensure($this->cache, 'yii\caching\CacheInterface') : null;
|
$this->cache = $this->enabled ? Instance::ensure($this->cache, 'yii\caching\CacheInterface') : null;
|
||||||
|
|
||||||
if ($this->cache instanceof CacheInterface && $this->getCachedContent() === false) {
|
if ($this->cache instanceof CacheInterface && $this->getCachedContent() === false) {
|
||||||
$this->getView()->cacheStack[] = $this;
|
$this->getView()->pushDynamicContent($this);
|
||||||
ob_start();
|
ob_start();
|
||||||
ob_implicit_flush(false);
|
ob_implicit_flush(false);
|
||||||
}
|
}
|
||||||
@ -104,7 +103,7 @@ class FragmentCache extends Widget
|
|||||||
if (($content = $this->getCachedContent()) !== false) {
|
if (($content = $this->getCachedContent()) !== false) {
|
||||||
echo $content;
|
echo $content;
|
||||||
} elseif ($this->cache instanceof CacheInterface) {
|
} elseif ($this->cache instanceof CacheInterface) {
|
||||||
array_pop($this->getView()->cacheStack);
|
$this->getView()->popDynamicContent();
|
||||||
|
|
||||||
$content = ob_get_clean();
|
$content = ob_get_clean();
|
||||||
if ($content === false || $content === '') {
|
if ($content === false || $content === '') {
|
||||||
@ -113,13 +112,9 @@ class FragmentCache extends Widget
|
|||||||
if (is_array($this->dependency)) {
|
if (is_array($this->dependency)) {
|
||||||
$this->dependency = Yii::createObject($this->dependency);
|
$this->dependency = Yii::createObject($this->dependency);
|
||||||
}
|
}
|
||||||
$data = [$content, $this->dynamicPlaceholders];
|
$data = [$content, $this->getDynamicPlaceholders()];
|
||||||
$this->cache->set($this->calculateKey(), $data, $this->duration, $this->dependency);
|
$this->cache->set($this->calculateKey(), $data, $this->duration, $this->dependency);
|
||||||
|
echo $this->updateDynamicContent($content, $this->getDynamicPlaceholders());
|
||||||
if (empty($this->getView()->cacheStack) && !empty($this->dynamicPlaceholders)) {
|
|
||||||
$content = $this->updateDynamicContent($content, $this->dynamicPlaceholders);
|
|
||||||
}
|
|
||||||
echo $content;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,33 +150,10 @@ class FragmentCache extends Widget
|
|||||||
return $this->_content;
|
return $this->_content;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($this->getView()->cacheStack)) {
|
$this->_content = $this->updateDynamicContent($this->_content, $placeholders, true);
|
||||||
// outermost cache: replace placeholder with dynamic content
|
|
||||||
$this->_content = $this->updateDynamicContent($this->_content, $placeholders);
|
|
||||||
}
|
|
||||||
foreach ($placeholders as $name => $statements) {
|
|
||||||
$this->getView()->addDynamicPlaceholder($name, $statements);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->_content;
|
return $this->_content;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Replaces placeholders in content by results of evaluated dynamic statements.
|
|
||||||
*
|
|
||||||
* @param string $content
|
|
||||||
* @param array $placeholders
|
|
||||||
* @return string final content
|
|
||||||
*/
|
|
||||||
protected function updateDynamicContent($content, $placeholders)
|
|
||||||
{
|
|
||||||
foreach ($placeholders as $name => $statements) {
|
|
||||||
$placeholders[$name] = $this->getView()->evaluateDynamicContent($statements);
|
|
||||||
}
|
|
||||||
|
|
||||||
return strtr($content, $placeholders);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a unique key used for storing the content in cache.
|
* Generates a unique key used for storing the content in cache.
|
||||||
* The key generated depends on both [[id]] and [[variations]].
|
* The key generated depends on both [[id]] and [[variations]].
|
||||||
|
Reference in New Issue
Block a user