*/
abstract class Mage_Core_Block_Abstract extends Varien_Object
{
/**
* Cache group Tag
*/
const CACHE_GROUP = 'block_html';
/**
* Cache tags data key
*/
const CACHE_TAGS_DATA_KEY = 'cache_tags';
/**
* Block name in layout
*
* @var string
*/
protected $_nameInLayout;
/**
* Parent layout of the block
*
* @var Mage_Core_Model_Layout
*/
protected $_layout;
/**
* Parent block
*
* @var Mage_Core_Block_Abstract
*/
protected $_parent;
/**
* Short alias of this block that was refered from parent
*
* @var string
*/
protected $_alias;
/**
* Suffix for name of anonymous block
*
* @var string
*/
protected $_anonSuffix;
/**
* Contains references to child block objects
*
* @var array
*/
protected $_children = array();
/**
* Sorted children list
*
* @var array
*/
protected $_sortedChildren = array();
/**
* Children blocks HTML cache array
*
* @var array
*/
protected $_childrenHtmlCache = array();
/**
* Arbitrary groups of child blocks
*
* @var array
*/
protected $_childGroups = array();
/**
* Request object
*
* @var Zend_Controller_Request_Http
*/
protected $_request;
/**
* Messages block instance
*
* @var Mage_Core_Block_Messages
*/
protected $_messagesBlock = null;
/**
* Whether this block was not explicitly named
*
* @var boolean
*/
protected $_isAnonymous = false;
/**
* Parent block
*
* @var Mage_Core_Block_Abstract
*/
protected $_parentBlock;
/**
* Block html frame open tag
* @var string
*/
protected $_frameOpenTag;
/**
* Block html frame close tag
* @var string
*/
protected $_frameCloseTag;
/**
* Url object
*
* @var Mage_Core_Model_Url
*/
protected static $_urlModel;
/**
* @var Varien_Object
*/
private static $_transportObject;
/**
* Array of block sort priority instructions
*
* @var array
*/
protected $_sortInstructions = array();
/**
* Factory instance
*
* @var Mage_Core_Model_Factory
*/
protected $_factory;
/**
* Initialize factory instance
*
* @param array $args
*/
public function __construct(array $args = array())
{
$this->_factory = !empty($args['core_factory']) ? $args['core_factory'] : Mage::getSingleton('core/factory');
parent::__construct($args);
}
/**
* Internal constructor, that is called from real constructor
*
* Please override this one instead of overriding real __construct constructor
*
*/
protected function _construct()
{
/**
* Please override this one instead of overriding real __construct constructor
*/
}
/**
* Retrieve request object
*
* @return Mage_Core_Controller_Request_Http
* @throws Exception
*/
public function getRequest()
{
$controller = Mage::app()->getFrontController();
if ($controller) {
$this->_request = $controller->getRequest();
} else {
throw new Exception(Mage::helper('core')->__("Can't retrieve request object"));
}
return $this->_request;
}
/**
* Retrieve parent block
*
* @return Mage_Core_Block_Abstract
*/
public function getParentBlock()
{
return $this->_parentBlock;
}
/**
* Set parent block
*
* @param Mage_Core_Block_Abstract $block
* @return Mage_Core_Block_Abstract
*/
public function setParentBlock(Mage_Core_Block_Abstract $block)
{
$this->_parentBlock = $block;
return $this;
}
/**
* Retrieve current action object
*
* @return Mage_Core_Controller_Varien_Action
*/
public function getAction()
{
return Mage::app()->getFrontController()->getAction();
}
/**
* Set layout object
*
* @param Mage_Core_Model_Layout $layout
* @return Mage_Core_Block_Abstract
*/
public function setLayout(Mage_Core_Model_Layout $layout)
{
$this->_layout = $layout;
Mage::dispatchEvent('core_block_abstract_prepare_layout_before', array('block' => $this));
$this->_prepareLayout();
Mage::dispatchEvent('core_block_abstract_prepare_layout_after', array('block' => $this));
return $this;
}
/**
* Preparing global layout
*
* You can redefine this method in child classes for changing layout
*
* @return Mage_Core_Block_Abstract
*/
protected function _prepareLayout()
{
return $this;
}
/**
* Retrieve layout object
*
* @return Mage_Core_Model_Layout
*/
public function getLayout()
{
return $this->_layout;
}
/**
* Check if block is using auto generated (Anonymous) name
* @return bool
*/
public function getIsAnonymous()
{
return $this->_isAnonymous;
}
/**
* Set the anonymous flag
*
* @param bool $flag
* @return Mage_Core_Block_Abstract
*/
public function setIsAnonymous($flag)
{
$this->_isAnonymous = (bool)$flag;
return $this;
}
/**
* Returns anonymous block suffix
*
* @return string
*/
public function getAnonSuffix()
{
return $this->_anonSuffix;
}
/**
* Set anonymous suffix for current block
*
* @param string $suffix
* @return Mage_Core_Block_Abstract
*/
public function setAnonSuffix($suffix)
{
$this->_anonSuffix = $suffix;
return $this;
}
/**
* Returns block alias
*
* @return string
*/
public function getBlockAlias()
{
return $this->_alias;
}
/**
* Set block alias
*
* @param string $alias
* @return Mage_Core_Block_Abstract
*/
public function setBlockAlias($alias)
{
$this->_alias = $alias;
return $this;
}
/**
* Set block's name in layout and unsets previous link if such exists.
*
* @param string $name
* @return Mage_Core_Block_Abstract
*/
public function setNameInLayout($name)
{
if (!empty($this->_nameInLayout) && $this->getLayout()) {
$this->getLayout()->unsetBlock($this->_nameInLayout)
->setBlock($name, $this);
}
$this->_nameInLayout = $name;
return $this;
}
/**
* Retrieve sorted list of children.
*
* @return array
*/
public function getSortedChildren()
{
$this->sortChildren();
return $this->_sortedChildren;
}
/**
* Set block attribute value
*
* Wrapper for method "setData"
*
* @param string $name
* @param mixed $value
* @return Mage_Core_Block_Abstract
*/
public function setAttribute($name, $value = null)
{
return $this->setData($name, $value);
}
/**
* Set child block
*
* @param string $alias
* @param Mage_Core_Block_Abstract $block
* @return Mage_Core_Block_Abstract
*/
public function setChild($alias, $block)
{
if (is_string($block)) {
$block = $this->getLayout()->getBlock($block);
}
if (!$block) {
return $this;
}
if ($block->getIsAnonymous()) {
$suffix = $block->getAnonSuffix();
if (empty($suffix)) {
$suffix = 'child' . sizeof($this->_children);
}
$blockName = $this->getNameInLayout() . '.' . $suffix;
if ($this->getLayout()) {
$this->getLayout()->unsetBlock($block->getNameInLayout())
->setBlock($blockName, $block);
}
$block->setNameInLayout($blockName);
$block->setIsAnonymous(false);
if (empty($alias)) {
$alias = $blockName;
}
}
$block->setParentBlock($this);
$block->setBlockAlias($alias);
$this->_children[$alias] = $block;
return $this;
}
/**
* Unset child block
*
* @param string $alias
* @return Mage_Core_Block_Abstract
*/
public function unsetChild($alias)
{
if (isset($this->_children[$alias])) {
/** @var Mage_Core_Block_Abstract $block */
$block = $this->_children[$alias];
$name = $block->getNameInLayout();
unset($this->_children[$alias]);
$key = array_search($name, $this->_sortedChildren);
if ($key !== false) {
unset($this->_sortedChildren[$key]);
}
}
return $this;
}
/**
* Call a child and unset it, if callback matched result
*
* $params will pass to child callback
* $params may be array, if called from layout with elements with same name, for example:
* ...value_1value_2value_3
*
* Or, if called like this:
* ...value_1value_2value_3
* - then it will be $params1, $params2, $params3
*
* It is no difference anyway, because they will be transformed in appropriate way.
*
* @param string $alias
* @param string $callback
* @param mixed $result
* @param array $params
* @return Mage_Core_Block_Abstract
*/
public function unsetCallChild($alias, $callback, $result, $params)
{
$child = $this->getChild($alias);
if ($child) {
$args = func_get_args();
$alias = array_shift($args);
$callback = array_shift($args);
$result = (string)array_shift($args);
if (!is_array($params)) {
$params = $args;
}
if ($result == call_user_func_array(array(&$child, $callback), $params)) {
$this->unsetChild($alias);
}
}
return $this;
}
/**
* Unset all children blocks
*
* @return Mage_Core_Block_Abstract
*/
public function unsetChildren()
{
$this->_children = array();
$this->_sortedChildren = array();
return $this;
}
/**
* Retrieve child block by name
*
* @param string $name
* @return mixed
*/
public function getChild($name = '')
{
if ($name === '') {
return $this->_children;
} elseif (isset($this->_children[$name])) {
return $this->_children[$name];
}
return false;
}
/**
* Retrieve child block HTML
*
* @param string $name
* @param boolean $useCache
* @param boolean $sorted
* @return string
*/
public function getChildHtml($name = '', $useCache = true, $sorted = false)
{
if ($name === '') {
if ($sorted) {
$children = array();
foreach ($this->getSortedChildren() as $childName) {
$children[$childName] = $this->getLayout()->getBlock($childName);
}
} else {
$children = $this->getChild();
}
$out = '';
foreach ($children as $child) {
$out .= $this->_getChildHtml($child->getBlockAlias(), $useCache);
}
return $out;
} else {
return $this->_getChildHtml($name, $useCache);
}
}
/**
* @param string $name Parent block name
* @param string $childName OPTIONAL Child block name
* @param bool $useCache OPTIONAL Use cache flag
* @param bool $sorted OPTIONAL @see getChildHtml()
* @return string
*/
public function getChildChildHtml($name, $childName = '', $useCache = true, $sorted = false)
{
if (empty($name)) {
return '';
}
$child = $this->getChild($name);
if (!$child) {
return '';
}
return $child->getChildHtml($childName, $useCache, $sorted);
}
/**
* Obtain sorted child blocks
*
* @return array
*/
public function getSortedChildBlocks()
{
$children = array();
foreach ($this->getSortedChildren() as $childName) {
$children[$childName] = $this->getLayout()->getBlock($childName);
}
return $children;
}
/**
* Retrieve child block HTML
*
* @param string $name
* @param boolean $useCache
* @return string
*/
protected function _getChildHtml($name, $useCache = true)
{
if ($useCache && isset($this->_childrenHtmlCache[$name])) {
return $this->_childrenHtmlCache[$name];
}
$child = $this->getChild($name);
if (!$child) {
$html = '';
} else {
$this->_beforeChildToHtml($name, $child);
$html = $child->toHtml();
}
$this->_childrenHtmlCache[$name] = $html;
return $html;
}
/**
* Prepare child block before generate html
*
* @param string $name
* @param Mage_Core_Block_Abstract $child
*/
protected function _beforeChildToHtml($name, $child)
{
}
/**
* Retrieve block html
*
* @param string $name
* @return string
*/
public function getBlockHtml($name)
{
if (!($layout = $this->getLayout()) && !($layout = $this->getAction()->getLayout())) {
return '';
}
if (!($block = $layout->getBlock($name))) {
return '';
}
return $block->toHtml();
}
/**
* Insert child block
*
* @param Mage_Core_Block_Abstract|string $block
* @param string $siblingName
* @param boolean $after
* @param string $alias
* @return object $this
*/
public function insert($block, $siblingName = '', $after = false, $alias = '')
{
if (is_string($block)) {
$block = $this->getLayout()->getBlock($block);
}
if (!$block) {
/*
* if we don't have block - don't throw exception because
* block can simply removed using layout method remove
*/
//Mage::throwException(Mage::helper('core')->__('Invalid block name to set child %s: %s', $alias, $block));
return $this;
}
if ($block->getIsAnonymous()) {
$this->setChild('', $block);
$name = $block->getNameInLayout();
} elseif ('' != $alias) {
$this->setChild($alias, $block);
$name = $block->getNameInLayout();
} else {
$name = $block->getNameInLayout();
$this->setChild($name, $block);
}
if ($siblingName === '') {
if ($after) {
array_push($this->_sortedChildren, $name);
} else {
array_unshift($this->_sortedChildren, $name);
}
} else {
$key = array_search($siblingName, $this->_sortedChildren);
if (false !== $key) {
if ($after) {
$key++;
}
array_splice($this->_sortedChildren, $key, 0, $name);
} else {
if ($after) {
array_push($this->_sortedChildren, $name);
} else {
array_unshift($this->_sortedChildren, $name);
}
}
$this->_sortInstructions[$name] = array($siblingName, (bool)$after, false !== $key);
}
return $this;
}
/**
* Sort block's children
*
* @param boolean $force force re-sort all children
* @return Mage_Core_Block_Abstract
*/
public function sortChildren($force = false)
{
foreach ($this->_sortInstructions as $name => $list) {
list($siblingName, $after, $exists) = $list;
if ($exists && !$force) {
continue;
}
$this->_sortInstructions[$name][2] = true;
$index = array_search($name, $this->_sortedChildren);
$siblingKey = array_search($siblingName, $this->_sortedChildren);
if ($index === false || $siblingKey === false) {
continue;
}
if ($after) {
// insert after block
if ($index == $siblingKey + 1) {
continue;
}
// remove sibling from array
array_splice($this->_sortedChildren, $index, 1, array());
// insert sibling after
array_splice($this->_sortedChildren, $siblingKey + 1, 0, array($name));
} else {
// insert before block
if ($index == $siblingKey - 1) {
continue;
}
// remove sibling from array
array_splice($this->_sortedChildren, $index, 1, array());
// insert sibling after
array_splice($this->_sortedChildren, $siblingKey, 0, array($name));
}
}
return $this;
}
/**
* Append child block
*
* @param Mage_Core_Block_Abstract|string $block
* @param string $alias
* @return Mage_Core_Block_Abstract
*/
public function append($block, $alias = '')
{
$this->insert($block, '', true, $alias);
return $this;
}
/**
* Make sure specified block will be registered in the specified child groups
*
* @param string $groupName
* @param Mage_Core_Block_Abstract $child
*/
public function addToChildGroup($groupName, Mage_Core_Block_Abstract $child)
{
if (!isset($this->_childGroups[$groupName])) {
$this->_childGroups[$groupName] = array();
}
if (!in_array($child->getBlockAlias(), $this->_childGroups[$groupName])) {
$this->_childGroups[$groupName][] = $child->getBlockAlias();
}
}
/**
* Add self to the specified group of parent block
*
* @param string $groupName
* @return Mage_Core_Block_Abstract
*/
public function addToParentGroup($groupName)
{
$this->getParentBlock()->addToChildGroup($groupName, $this);
return $this;
}
/**
* Get a group of child blocks
*
* Returns an array of =>
* or an array of =>
* The callback currently supports only $this methods and passes the alias as parameter
*
* @param string $groupName
* @param string $callback
* @param bool $skipEmptyResults
* @return array
*/
public function getChildGroup($groupName, $callback = null, $skipEmptyResults = true)
{
$result = array();
if (!isset($this->_childGroups[$groupName])) {
return $result;
}
foreach ($this->getSortedChildBlocks() as $block) {
$alias = $block->getBlockAlias();
if (in_array($alias, $this->_childGroups[$groupName])) {
if ($callback) {
$row = $this->$callback($alias);
if (!$skipEmptyResults || $row) {
$result[$alias] = $row;
}
} else {
$result[$alias] = $block;
}
}
}
return $result;
}
/**
* Get a value from child block by specified key
*
* @param string $alias
* @param string $key
* @return mixed
*/
public function getChildData($alias, $key = '')
{
$child = $this->getChild($alias);
if ($child) {
return $child->getData($key);
}
}
/**
* Before rendering html, but after trying to load cache
*
* @return Mage_Core_Block_Abstract
*/
protected function _beforeToHtml()
{
return $this;
}
/**
* Specify block output frame tags
*
* @param $openTag
* @param $closeTag
* @return Mage_Core_Block_Abstract
*/
public function setFrameTags($openTag, $closeTag = null)
{
$this->_frameOpenTag = $openTag;
if ($closeTag) {
$this->_frameCloseTag = $closeTag;
} else {
$this->_frameCloseTag = '/' . $openTag;
}
return $this;
}
/**
* Produce and return block's html output
*
* It is a final method, but you can override _toHtml() method in descendants if needed.
*
* @return string
*/
final public function toHtml()
{
Mage::dispatchEvent('core_block_abstract_to_html_before', array('block' => $this));
if (Mage::getStoreConfig('advanced/modules_disable_output/' . $this->getModuleName())) {
return '';
}
$html = $this->_loadCache();
if ($html === false) {
$translate = Mage::getSingleton('core/translate');
/** @var $translate Mage_Core_Model_Translate */
if ($this->hasData('translate_inline')) {
$translate->setTranslateInline($this->getData('translate_inline'));
}
$this->_beforeToHtml();
$html = $this->_toHtml();
$this->_saveCache($html);
if ($this->hasData('translate_inline')) {
$translate->setTranslateInline(true);
}
}
$html = $this->_afterToHtml($html);
/**
* Check framing options
*/
if ($this->_frameOpenTag) {
$html = '<'.$this->_frameOpenTag.'>'.$html.'<'.$this->_frameCloseTag.'>';
}
/**
* Use single transport object instance for all blocks
*/
if (self::$_transportObject === null) {
self::$_transportObject = new Varien_Object;
}
self::$_transportObject->setHtml($html);
Mage::dispatchEvent('core_block_abstract_to_html_after',
array('block' => $this, 'transport' => self::$_transportObject));
$html = self::$_transportObject->getHtml();
return $html;
}
/**
* Processing block html after rendering
*
* @param string $html
* @return string
*/
protected function _afterToHtml($html)
{
return $html;
}
/**
* Override this method in descendants to produce html
*
* @return string
*/
protected function _toHtml()
{
return '';
}
/**
* Returns url model class name
*
* @return string
*/
protected function _getUrlModelClass()
{
return 'core/url';
}
/**
* Create and return url object
*
* @return Mage_Core_Model_Url
*/
protected function _getUrlModel()
{
return Mage::getModel($this->_getUrlModelClass());
}
/**
* Generate url by route and parameters
*
* @param string $route
* @param array $params
* @return string
*/
public function getUrl($route = '', $params = array())
{
return $this->_getUrlModel()->getUrl($route, $params);
}
/**
* Generate base64-encoded url by route and parameters
*
* @param string $route
* @param array $params
* @return string
*/
public function getUrlBase64($route = '', $params = array())
{
return Mage::helper('core')->urlEncode($this->getUrl($route, $params));
}
/**
* Generate url-encoded url by route and parameters
*
* @param string $route
* @param array $params
* @return string
*/
public function getUrlEncoded($route = '', $params = array())
{
return Mage::helper('core')->urlEncode($this->getUrl($route, $params));
}
/**
* Retrieve url of skins file
*
* @param string $file path to file in skin
* @param array $params
* @return string
*/
public function getSkinUrl($file = null, array $params = array())
{
return Mage::getDesign()->getSkinUrl($file, $params);
}
/**
* Retrieve messages block
*
* @return Mage_Core_Block_Messages
*/
public function getMessagesBlock()
{
if (is_null($this->_messagesBlock)) {
return $this->getLayout()->getMessagesBlock();
}
return $this->_messagesBlock;
}
/**
* Set messages block
*
* @param Mage_Core_Block_Messages $block
* @return Mage_Core_Block_Abstract
*/
public function setMessagesBlock(Mage_Core_Block_Messages $block)
{
$this->_messagesBlock = $block;
return $this;
}
/**
* Return block helper
*
* @param string $type
* @return Mage_Core_Block_Abstract
*/
public function getHelper($type)
{
return $this->getLayout()->getBlockSingleton($type);
}
/**
* Returns helper object
*
* @param string $name
* @return Mage_Core_Block_Abstract
*/
public function helper($name)
{
if ($this->getLayout()) {
return $this->getLayout()->helper($name);
}
return Mage::helper($name);
}
/**
* Retrieve formatting date
*
* @param string $date
* @param string $format
* @param bool $showTime
* @return string
*/
public function formatDate($date = null, $format = Mage_Core_Model_Locale::FORMAT_TYPE_SHORT, $showTime = false)
{
return $this->helper('core')->formatDate($date, $format, $showTime);
}
/**
* Retrieve formatting time
*
* @param string $time
* @param string $format
* @param bool $showDate
* @return string
*/
public function formatTime($time = null, $format = Mage_Core_Model_Locale::FORMAT_TYPE_SHORT, $showDate = false)
{
return $this->helper('core')->formatTime($time, $format, $showDate);
}
/**
* Retrieve module name of block
*
* @return string
*/
public function getModuleName()
{
$module = $this->getData('module_name');
if (is_null($module)) {
$class = get_class($this);
$module = substr($class, 0, strpos($class, '_Block'));
$this->setData('module_name', $module);
}
return $module;
}
/**
* Translate block sentence
*
* @return string
*/
public function __()
{
$args = func_get_args();
$expr = new Mage_Core_Model_Translate_Expr(array_shift($args), $this->getModuleName());
array_unshift($args, $expr);
return Mage::app()->getTranslator()->translate($args);
}
/**
* @deprecated after 1.4.0.0-rc1
* @see self::escapeHtml()
*/
public function htmlEscape($data, $allowedTags = null)
{
return $this->escapeHtml($data, $allowedTags);
}
/**
* Escape html entities
*
* @param mixed $data
* @param array $allowedTags
* @return string
*/
public function escapeHtml($data, $allowedTags = null)
{
return $this->helper('core')->escapeHtml($data, $allowedTags);
}
/**
* Wrapper for standard strip_tags() function with extra functionality for html entities
*
* @param string $data
* @param string $allowableTags
* @param bool $allowHtmlEntities
* @return string
*/
public function stripTags($data, $allowableTags = null, $allowHtmlEntities = false)
{
return $this->helper('core')->stripTags($data, $allowableTags, $allowHtmlEntities);
}
/**
* @deprecated after 1.4.0.0-rc1
* @see self::escapeUrl()
*/
public function urlEscape($data)
{
return $this->escapeUrl($data);
}
/**
* Escape html entities in url
*
* @param string $data
* @return string
*/
public function escapeUrl($data)
{
return $this->helper('core')->escapeUrl($data);
}
/**
* Escape quotes inside html attributes
* Use $addSlashes = false for escaping js that inside html attribute (onClick, onSubmit etc)
*
* @param string $data
* @param bool $addSlashes
* @return string
*/
public function quoteEscape($data, $addSlashes = false)
{
return $this->helper('core')->quoteEscape($data, $addSlashes);
}
/**
* Escape quotes in java scripts
*
* @param mixed $data
* @param string $quote
* @return mixed
*/
public function jsQuoteEscape($data, $quote = '\'')
{
return $this->helper('core')->jsQuoteEscape($data, $quote);
}
/**
* Alias for getName method.
*
* @return string
*/
public function getNameInLayout()
{
return $this->_nameInLayout;
}
/**
* Get chilren blocks count
* @return int
*/
public function countChildren()
{
return count($this->_children);
}
/**
* Prepare url for save to cache
*
* @return Mage_Core_Block_Abstract
*/
protected function _beforeCacheUrl()
{
if (Mage::app()->useCache(self::CACHE_GROUP)) {
Mage::app()->setUseSessionVar(true);
}
return $this;
}
/**
* Replace URLs from cache
*
* @param string $html
* @return string
*/
protected function _afterCacheUrl($html)
{
if (Mage::app()->useCache(self::CACHE_GROUP)) {
Mage::app()->setUseSessionVar(false);
Varien_Profiler::start('CACHE_URL');
$html = Mage::getSingleton($this->_getUrlModelClass())->sessionUrlVar($html);
Varien_Profiler::stop('CACHE_URL');
}
return $html;
}
/**
* Get cache key informative items
* Provide string array key to share specific info item with FPC placeholder
*
* @return array
*/
public function getCacheKeyInfo()
{
return array(
$this->getNameInLayout()
);
}
/**
* Get Key for caching block content
*
* @return string
*/
public function getCacheKey()
{
if ($this->hasData('cache_key')) {
return $this->getData('cache_key');
}
/**
* don't prevent recalculation by saving generated cache key
* because of ability to render single block instance with different data
*/
$key = $this->getCacheKeyInfo();
//ksort($key); // ignore order
$key = array_values($key); // ignore array keys
$key = implode('|', $key);
$key = sha1($key);
return $key;
}
/**
* Get tags array for saving cache
*
* @return array
*/
public function getCacheTags()
{
$tagsCache = Mage::app()->loadCache($this->_getTagsCacheKey());
if ($tagsCache) {
$tags = json_decode($tagsCache);
}
if (!isset($tags) || !is_array($tags) || empty($tags)) {
$tags = !$this->hasData(self::CACHE_TAGS_DATA_KEY) ? array() : $this->getData(self::CACHE_TAGS_DATA_KEY);
if (!in_array(self::CACHE_GROUP, $tags)) {
$tags[] = self::CACHE_GROUP;
}
}
return array_unique($tags);
}
/**
* Add tag to block
*
* @param string|array $tag
* @return Mage_Core_Block_Abstract
*/
public function addCacheTag($tag)
{
$tag = is_array($tag) ? $tag : array($tag);
$tags = !$this->hasData(self::CACHE_TAGS_DATA_KEY) ?
$tag : array_merge($this->getData(self::CACHE_TAGS_DATA_KEY), $tag);
$this->setData(self::CACHE_TAGS_DATA_KEY, $tags);
return $this;
}
/**
* Add tags from specified model to current block
*
* @param Mage_Core_Model_Abstract $model
* @return Mage_Core_Block_Abstract
*/
public function addModelTags(Mage_Core_Model_Abstract $model)
{
$cacheTags = $model->getCacheIdTags();
if (false !== $cacheTags) {
$this->addCacheTag($cacheTags);
}
return $this;
}
/**
* Get block cache life time
*
* @return int
*/
public function getCacheLifetime()
{
if (!$this->hasData('cache_lifetime')) {
return null;
}
return $this->getData('cache_lifetime');
}
/**
* Load block html from cache storage
*
* @return string | false
*/
protected function _loadCache()
{
if (is_null($this->getCacheLifetime()) || !Mage::app()->useCache(self::CACHE_GROUP)) {
return false;
}
$cacheKey = $this->getCacheKey();
/** @var $session Mage_Core_Model_Session */
$session = Mage::getSingleton('core/session');
$cacheData = Mage::app()->loadCache($cacheKey);
if ($cacheData) {
$cacheData = str_replace(
$this->_getSidPlaceholder($cacheKey),
$session->getSessionIdQueryParam() . '=' . $session->getEncryptedSessionId(),
$cacheData
);
}
return $cacheData;
}
/**
* Save block content to cache storage
*
* @param string $data
* @return Mage_Core_Block_Abstract
*/
protected function _saveCache($data)
{
if (is_null($this->getCacheLifetime()) || !Mage::app()->useCache(self::CACHE_GROUP)) {
return false;
}
$cacheKey = $this->getCacheKey();
/** @var $session Mage_Core_Model_Session */
$session = Mage::getSingleton('core/session');
$data = str_replace(
$session->getSessionIdQueryParam() . '=' . $session->getEncryptedSessionId(),
$this->_getSidPlaceholder($cacheKey),
$data
);
$tags = $this->getCacheTags();
Mage::app()->saveCache($data, $cacheKey, $tags, $this->getCacheLifetime());
Mage::app()->saveCache(
json_encode($tags),
$this->_getTagsCacheKey($cacheKey),
$tags,
$this->getCacheLifetime()
);
return $this;
}
/**
* Get cache key for tags
*
* @param string $cacheKey
* @return string
*/
protected function _getTagsCacheKey($cacheKey = null)
{
$cacheKey = !empty($cacheKey) ? $cacheKey : $this->getCacheKey();
$cacheKey = md5($cacheKey . '_tags');
return $cacheKey;
}
/**
* Get SID placeholder for cache
*
* @param null|string $cacheKey
* @return string
*/
protected function _getSidPlaceholder($cacheKey = null)
{
if (is_null($cacheKey)) {
$cacheKey = $this->getCacheKey();
}
return '';
}
/**
* Collect and retrieve items tags.
* Item should implements Mage_Core_Model_Abstract::getCacheIdTags method
*
* @param array|Varien_Data_Collection $items
* @return array
*/
public function getItemsTags($items)
{
$tags = array();
/** @var $item Mage_Core_Model_Abstract */
foreach($items as $item) {
$itemTags = $item->getCacheIdTags();
if (false === $itemTags) {
continue;
}
$tags = array_merge($tags, $itemTags);
}
return $tags;
}
}