Browse Source

finished fragment caching.

tags/2.0.0-beta
Qiang Xue 12 years ago
parent
commit
de5c304f64
  1. 2
      framework/YiiBase.php
  2. 6
      framework/base/Component.php
  3. 8
      framework/base/Object.php
  4. 60
      framework/base/View.php
  5. 30
      framework/widgets/FragmentCache.php

2
framework/YiiBase.php

@ -298,7 +298,7 @@ class YiiBase
}
}
if (isset($classFile, $alias)) {
if (isset($classFile, $alias) && is_file($classFile)) {
if (!YII_DEBUG || basename(realpath($classFile)) === basename($alias) . '.php') {
include($classFile);
return true;

6
framework/base/Component.php

@ -58,7 +58,7 @@ class Component extends \yii\base\Object
}
}
}
throw new UnknownPropertyException('Getting unknown property: ' . get_class($this) . '.' . $name);
throw new UnknownPropertyException('Getting unknown property: ' . get_class($this) . '::' . $name);
}
/**
@ -105,9 +105,9 @@ class Component extends \yii\base\Object
}
}
if (method_exists($this, 'get' . $name)) {
throw new InvalidCallException('Setting read-only property: ' . get_class($this) . '.' . $name);
throw new InvalidCallException('Setting read-only property: ' . get_class($this) . '::' . $name);
} else {
throw new UnknownPropertyException('Setting unknown property: ' . get_class($this) . '.' . $name);
throw new UnknownPropertyException('Setting unknown property: ' . get_class($this) . '::' . $name);
}
}

8
framework/base/Object.php

@ -65,7 +65,7 @@ class Object
if (method_exists($this, $getter)) {
return $this->$getter();
} else {
throw new UnknownPropertyException('Getting unknown property: ' . get_class($this) . '.' . $name);
throw new UnknownPropertyException('Getting unknown property: ' . get_class($this) . '::' . $name);
}
}
@ -86,9 +86,9 @@ class Object
if (method_exists($this, $setter)) {
$this->$setter($value);
} elseif (method_exists($this, 'get' . $name)) {
throw new InvalidCallException('Setting read-only property: ' . get_class($this) . '.' . $name);
throw new InvalidCallException('Setting read-only property: ' . get_class($this) . '::' . $name);
} else {
throw new UnknownPropertyException('Setting unknown property: ' . get_class($this) . '.' . $name);
throw new UnknownPropertyException('Setting unknown property: ' . get_class($this) . '::' . $name);
}
}
@ -129,7 +129,7 @@ class Object
if (method_exists($this, $setter)) {
$this->$setter(null);
} elseif (method_exists($this, 'get' . $name)) {
throw new InvalidCallException('Unsetting read-only property: ' . get_class($this) . '.' . $name);
throw new InvalidCallException('Unsetting read-only property: ' . get_class($this) . '::' . $name);
}
}

60
framework/base/View.php

@ -45,11 +45,21 @@ class View extends Component
* through this property.
*/
public $clips;
/**
* @var Widget[] the widgets that are currently not ended
* @var Widget[] the widgets that are currently being rendered (not ended). This property
* is maintained by [[beginWidget()]] and [[endWidget()]] methods. Do not modify it directly.
*/
public $widgetStack = array();
/**
* @var array a list of currently active fragment cache widgets. This property
* is used internally to implement the content caching feature. Do not modify it.
*/
public $cacheStack = array();
/**
* @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.
*/
private $_widgetStack = array();
public $dynamicPlaceholders = array();
/**
@ -156,20 +166,47 @@ class View extends Component
return ob_get_clean();
}
/**
* Renders dynamic content returned by the given PHP statements.
* This method is mainly used together with content caching (fragment caching and page caching)
* when some portions of the content (called *dynamic content*) should not be cached.
* The dynamic content must be returned by some PHP statements.
* @param string $statements the PHP statements for generating the dynamic content.
* @return string the placeholder of the dynamic content, or the dynamic content if there is no
* active content cache currently.
*/
public function renderDynamic($statements)
{
if (!empty($this->cachingStack)) {
$n = count($this->_dynamicOutput);
if (!empty($this->cacheStack)) {
$n = count($this->dynamicPlaceholders);
$placeholder = "<![CDATA[YDP-$n]]>";
foreach ($this->cachingStack as $cache) {
$cache->dynamicPlaceholders[$placeholder] = $statements;
}
$this->addDynamicPlaceholder($placeholder, $statements);
return $placeholder;
} else {
return $this->evaluateDynamicContent($statements);
}
}
/**
* Adds a placeholder for dynamic content.
* This method is internally used.
* @param string $placeholder the placeholder name
* @param string $statements the PHP statements for generating the dynamic content
*/
public function addDynamicPlaceholder($placeholder, $statements)
{
foreach ($this->cacheStack as $cache) {
$cache->dynamicPlaceholders[$placeholder] = $statements;
}
$this->dynamicPlaceholders[$placeholder] = $statements;
}
/**
* Evaluates the given PHP statements.
* This method is mainly used internally to implement dynamic content feature.
* @param string $statements the PHP statements to be evaluated.
* @return mixed the return value of the PHP statements.
*/
public function evaluateDynamicContent($statements)
{
return eval($statements);
@ -267,7 +304,7 @@ class View extends Component
public function beginWidget($class, $properties = array())
{
$widget = $this->createWidget($class, $properties);
$this->_widgetStack[] = $widget;
$this->widgetStack[] = $widget;
return $widget;
}
@ -281,7 +318,7 @@ class View extends Component
*/
public function endWidget()
{
$widget = array_pop($this->_widgetStack);
$widget = array_pop($this->widgetStack);
if ($widget instanceof Widget) {
$widget->run();
return $widget;
@ -363,8 +400,9 @@ class View extends Component
public function beginCache($id, $properties = array())
{
$properties['id'] = $id;
$properties['view'] = $this;
/** @var $cache \yii\widgets\FragmentCache */
$cache = $this->beginWidget('yii\widgets\OutputCache', $properties);
$cache = $this->beginWidget('yii\widgets\FragmentCache', $properties);
if ($cache->getCachedContent() !== false) {
$this->endCache();
return false;

30
framework/widgets/FragmentCache.php

@ -67,7 +67,8 @@ class FragmentCache extends Widget
*/
public $view;
/**
* @var array
* @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;
@ -83,8 +84,8 @@ class FragmentCache extends Widget
if ($this->view === null) {
$this->view = Yii::$app->getView();
}
if ($this->getCachedContent() === false && $this->getCache() !== null) {
array_push($this->view->cachingStack, $this);
if ($this->getCache() !== null && $this->getCachedContent() === false) {
$this->view->cacheStack[] = $this;
ob_start();
ob_implicit_flush(false);
}
@ -100,14 +101,18 @@ class FragmentCache extends Widget
{
if (($content = $this->getCachedContent()) !== false) {
echo $content;
} elseif (($cache = $this->getCache()) !== false) {
} elseif (($cache = $this->getCache()) !== null) {
$content = ob_get_clean();
array_pop($this->view->cachingStack);
array_pop($this->view->cacheStack);
if (is_array($this->dependency)) {
$this->dependency = Yii::createObject($this->dependency);
}
$data = array($content, $this->dynamicPlaceholders);
$cache->set($this->calculateKey(), $data, $this->duration, $this->dependency);
if ($this->view->cacheStack === array() && !empty($this->dynamicPlaceholders)) {
$content = $this->updateDynamicContent($content, $this->dynamicPlaceholders);
}
echo $content;
}
}
@ -131,10 +136,13 @@ class FragmentCache extends Widget
if (is_array($data) && count($data) === 2) {
list ($content, $placeholders) = $data;
if (is_array($placeholders) && count($placeholders) > 0) {
if ($this->view->cacheStack === array()) {
// outermost cache: replace placeholder with dynamic content
$content = $this->updateDynamicContent($content, $placeholders);
}
foreach ($placeholders as $name => $statements) {
$placeholders[$name] = $this->view->evaluateDynamicContent($statements);
$this->view->addDynamicPlaceholder($name, $statements);
}
$content = strtr($content, $placeholders);
}
$this->_content = $content;
}
@ -143,6 +151,14 @@ class FragmentCache extends Widget
return $this->_content;
}
protected function updateDynamicContent($content, $placeholders)
{
foreach ($placeholders as $name => $statements) {
$placeholders[$name] = $this->view->evaluateDynamicContent($statements);
}
return strtr($content, $placeholders);
}
/**
* Generates a unique key used for storing the content in cache.
* The key generated depends on both [[id]] and [[variations]].

Loading…
Cancel
Save