Edit cacheTags and Parameters via events in Lesti_Fpc 1.3.2

In Lesti_Fpc 1.3.2 I have added the possibility to edit the cacheTags and Parameters via an event. The idea of the Fpc was very clear and simple, but every day I get requests from developers with problems, that aren't that simple. For example oblomovx wanted to Disable Cleaning of Categories after product save. Maybe 98% of all Fpc users didn't need the possibilty to disable this functionality. Or riznmage wanted to Add AJAX parameter to make a differnce between requests that are made by ajax and normal requests. I can understand the need of such a thing, but on the other site I can't implement every crazy idea or I just think that it is wrong to make a ajax request on a action that isn't normally made for it. To let the Fpc simple, but also give those people the possiblity for there workflow I have made it like Magento. I have dispatched some events to work a little bit more advanced with the behavior of the Fpc.

What are cacheTags?

The Fpc uses cacheTags to clean related pages. For example the save of a product will also flush all category pages that are related to that product. Before a page is saved to the cache, it will be binded to some cacheTags. That happens in the function httpResponseSendBefore of Lesti_Fpc_Model_Observer

$this->_getFpc()->save(time() . $body, $key, $this->_cacheTags);
Every developer now has the possibility to edit those tags before the page will be saved via an event. For example oblomovx can remove all product cachetags from category pages.
// edit cacheTags via event
$cacheTags = new Varien_Object();
$cacheTags->setValue($this->_cacheTags);
Mage::dispatchEvent(
    'fpc_observer_collect_cache_tags',
    array('cache_tags' => $cacheTags)
);
$this->_cacheTags = $cacheTags->getValue();
That is the same way, you can edit put additional conditions to Mage_SalesRule_Model_Rule_Condition_Combine.
$additional = new Varien_Object();
Mage::dispatchEvent('salesrule_rule_condition_combine', array('additional' => $additional));
if ($additionalConditions = $additional->getConditions()) {
    $conditions = array_merge_recursive($conditions, $additionalConditions);
}
At the end of this post I give an example how use this event.

What are parameters?

Parameters is maybe the wrong name. Normally parameters are just the parameters that are part of the request. That has historically reasons, cause at the beginning of the Fpc I only made a differnce between two pages with there parameters from the request. But at the moment, there are also things like currency, design and so on. Maybe two requests are mostly the same, but one request will be handled with the mobile theme and the other with the default theme. So the Fpc has to cache two different pages. The Fpc collects all those parameters in _getParams of Lesti_Fpc_Helper_Data and generates a cacheKey out of them.

public function getKey($postfix = '_page')
{
    return sha1($this->_getParams()) . $postfix;
}
Similar to the cacheTags, I have dispatched an event.
// edit parameters via event
$parameters = new Varien_Object();
$parameters->setValue($params);
Mage::dispatchEvent(
    'fpc_helper_collect_params',
    array('parameters' => $parameters)
);
$params = $parameters->getValue();
Mage::register(self::REGISTRY_KEY_PARAMS, serialize($params));
So that a develoepr can edit those parameters. For example Denys Kyselov can create a different cache entry for every logged in customer.

A simple Example

This isn't just an simple example. This shows, that the Fpc itself uses now it's own events. You can listen to the events with your config.xml.

<?xml version="1.0"?>
<config>
    <!-- ... -->
    <global>
        <!-- ... -->
        <events>
            <fpc_helper_collect_params>
                <observers>
                    <fpc_fpc_helper_collect_params>
                        <class>fpc/observer_parameters</class>
                        <type>singleton</type>
                        <method>fpcHelperCollectParams</method>
                    </fpc_fpc_helper_collect_params>
                </observers>
            </fpc_helper_collect_params>
            <fpc_observer_collect_cache_tags>
                <observers>
                    <fpc_fpc_observer_collect_cache_tags>
                        <class>fpc/observer_tags</class>
                        <type>singleton</type>
                        <method>fpcObserverCollectCacheTags</method>
                    </fpc_fpc_observer_collect_cache_tags>
                </observers>
            </fpc_observer_collect_cache_tags>
        </events>
        <!-- ... -->
    </global>
    <!-- ... -->
</config>
In the fucntion fpcHelperCollectParams of Lesti_Fpc_Model_Observer_Parameters I'm listening to the event fpc_helper_collect_params and I add the storeCode, the currency and the desing parameters.
    public function fpcHelperCollectParams($observer)
    {
        $params = array();
        // store
        $storeCode = Mage::app()->getStore(true)->getCode();
        if ($storeCode) {
            $params['store'] = $storeCode;
        }
        // currency
        $currencyCode = Mage::app()->getStore()->getCurrentCurrencyCode();
        if ($currencyCode) {
            $params['currency'] = $currencyCode;
        }
        // design
        $design = Mage::getDesign();
        $params['design'] = $design->getPackageName().'_'.
            $design->getTheme('template');

        $parameters = $observer->getEvent()->getParameters();
        $additionalParams = $parameters->getValue();
        $additionalParams = array_merge($additionalParams, $params);
        $parameters->setValue($additionalParams);
    }
And in the function fpcObserverCollectCacheTags of Lesti_Fpc_Model_Observer_Tags I'm listening to the event fpc_observer_collect_cache_tags and add the cacheTags of the current layout handle.
    public function fpcObserverCollectCacheTags($observer)
    {
        /** @var Lesti_Fpc_Helper_Data $helper */
        $helper = Mage::helper('fpc');
        $fullActionName = $helper->getFullActionName();
        $cacheTags = array();
        $request = Mage::app()->getRequest();
        switch ($fullActionName) {
            case 'cms_index_index' :
                $cacheTags = $this->getCmsIndexIndexCacheTags();
                break;
            case 'cms_page_view' :
                $cacheTags = $this->getCmsPageViewCacheTags($request);
                break;
            case 'catalog_product_view' :
                $cacheTags = $this->getCatalogProductViewCacheTags($request);
                break;
            case 'catalog_category_view' :
                $cacheTags = $this->getCatalogCategoryViewCacheTags($request);
                break;
        }

        $cacheTagObject = $observer->getEvent()->getCacheTags();
        $additionalCacheTags = $cacheTagObject->getValue();
        $additionalCacheTags = array_merge($additionalCacheTags, $cacheTags);
        $cacheTagObject->setValue($additionalCacheTags);
    }
At the end of both functions you can see, that I merge the collected cacheTags or parameters with the existing one and put them back into the object.

Next Previous