banClientEsiCache()   A
last analyzed

Complexity

Conditions 5
Paths 4

Size

Total Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 25
rs 9.2088
c 0
b 0
f 0
cc 5
nc 4
nop 1
1
<?php
2
3
/**
4
 * Nexcess.net Turpentine Extension for Magento
5
 * Copyright (C) 2012  Nexcess.net L.L.C.
6
 *
7
 * This program is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 2 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License along
18
 * with this program; if not, write to the Free Software Foundation, Inc.,
19
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
 */
21
22
/**
23
 * Most of this is taken from @link https://github.com/huguesalary/Magento-Varnish
24
 */
25
26
class Nexcessnet_Turpentine_Model_Observer_Ban extends Varien_Event_Observer {
27
28
    /**
29
     * Cache the varnish admin object
30
     * @var Nexcessnet_Turpentine_Model_Varnish_Admin
31
     */
32
    protected $_varnishAdmin = null;
33
    /**
34
     * Flag to prevent doing the ESI cache clear more than once per request
35
     * @var boolean
36
     */
37
    protected $_esiClearFlag = array();
38
39
    /**
40
     * Clear the ESI block cache for a specific client
41
     *
42
     * Events:
43
     *     the events are applied dynamically according to what events are set
44
     *     for the various blocks' esi policies
45
     *
46
     * @param  Varien_Object $eventObject
47
     * @return null
48
     */
49
    public function banClientEsiCache($eventObject) {
50
        $eventName = $eventObject->getEvent()->getName();
51
        if (Mage::helper('turpentine/esi')->getEsiEnabled() &&
52
                ! in_array($eventName, $this->_esiClearFlag)) {
53
            $sessionId = Mage::app()->getRequest()->getCookie('frontend');
54
            if ($sessionId) {
55
                $result = $this->_getVarnishAdmin()->flushExpression(
56
                    'obj.http.X-Varnish-Session', '==', $sessionId,
57
                    '&&', 'obj.http.X-Turpentine-Flush-Events', '~',
58
                    $eventName );
59
                Mage::dispatchEvent('turpentine_ban_client_esi_cache', $result);
60
                if ($this->_checkResult($result)) {
61
                    Mage::helper('turpentine/debug')
62
                        ->logDebug('Cleared ESI cache for client (%s) on event: %s',
63
                            $sessionId, $eventName);
64
                } else {
65
                    Mage::helper('turpentine/debug')
66
                        ->logWarn(
67
                            'Failed to clear Varnish ESI cache for client: %s',
68
                            $sessionId );
69
                }
70
            }
71
            $this->_esiClearFlag[] = $eventName;
72
        }
73
    }
74
75
    /**
76
     * Ban a specific product page from the cache
77
     *
78
     * Events:
79
     *     catalog_product_save_commit_after
80
     *
81
     * @param  Varien_Object $eventObject
82
     * @return null
83
     */
84
    public function banProductPageCache($eventObject) {
85
        if (Mage::helper('turpentine/varnish')->getVarnishEnabled()) {
86
            $banHelper = Mage::helper('turpentine/ban');
87
            $product = $eventObject->getProduct();
88
            $urlPattern = $banHelper->getProductBanRegex($product);
89
            $result = $this->_getVarnishAdmin()->flushUrl($urlPattern);
90
            Mage::dispatchEvent('turpentine_ban_product_cache', $result);
91
            $cronHelper = Mage::helper('turpentine/cron');
92 View Code Duplication
            if ($this->_checkResult($result) &&
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
93
                    $cronHelper->getCrawlerEnabled()) {
94
                $cronHelper->addProductToCrawlerQueue($product);
95
                foreach ($banHelper->getParentProducts($product)
96
                        as $parentProduct) {
97
                    $cronHelper->addProductToCrawlerQueue($parentProduct);
98
                }
99
            }
100
        }
101
    }
102
103
    /**
104
     * Ban a product page from the cache if it's stock status changed
105
     *
106
     * Events:
107
     *     cataloginventory_stock_item_save_after
108
     *
109
     * @param  Varien_Object $eventObject
110
     * @return null
111
     */
112
    public function banProductPageCacheCheckStock($eventObject) {
113
        if (Mage::helper('turpentine/varnish')->getVarnishEnabled()) {
114
            $item = $eventObject->getItem();
115
            if ($item->getStockStatusChangedAutomatically() ||
116
                    ($item->getOriginalInventoryQty() <= 0 &&
117
                        $item->getQty() > 0 &&
118
                        $item->getQtyCorrection() > 0)) {
119
                $banHelper = Mage::helper('turpentine/ban');
120
                $cronHelper = Mage::helper('turpentine/cron');
121
                $product = Mage::getModel('catalog/product')
122
                    ->load($item->getProductId());
123
                $urlPattern = $banHelper->getProductBanRegex($product);
124
                $result = $this->_getVarnishAdmin()->flushUrl($urlPattern);
125
                Mage::dispatchEvent('turpentine_ban_product_cache_check_stock',
126
                    $result);
127 View Code Duplication
                if ($this->_checkResult($result) &&
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
128
                        $cronHelper->getCrawlerEnabled()) {
129
                    $cronHelper->addProductToCrawlerQueue($product);
130
                    foreach ($banHelper->getParentProducts($product)
131
                            as $parentProduct) {
132
                        $cronHelper->addProductToCrawlerQueue($parentProduct);
133
                    }
134
                }
135
            }
136
        }
137
    }
138
139
    /**
140
     * Ban a category page, and any subpages on save
141
     *
142
     * Events:
143
     *     catalog_category_save_commit_after
144
     *
145
     * @param  Varien_Object $eventObject
146
     * @return null
147
     */
148 View Code Duplication
    public function banCategoryCache($eventObject) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
149
        if (Mage::helper('turpentine/varnish')->getVarnishEnabled()) {
150
            $category = $eventObject->getCategory();
151
            $result = $this->_getVarnishAdmin()->flushUrl($category->getUrlKey());
152
            Mage::dispatchEvent('turpentine_ban_category_cache', $result);
153
            $cronHelper = Mage::helper('turpentine/cron');
154
            if ($this->_checkResult($result) &&
155
                    $cronHelper->getCrawlerEnabled()) {
156
                $cronHelper->addCategoryToCrawlerQueue($category);
157
            }
158
        }
159
    }
160
161
    /**
162
     * Clear the media (CSS/JS) cache, corresponds to the buttons on the cache
163
     * page in admin
164
     *
165
     * Events:
166
     *     clean_media_cache_after
167
     *
168
     * @param  Varien_Object $eventObject
169
     * @return null
170
     */
171 View Code Duplication
    public function banMediaCache($eventObject) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
172
        if (Mage::helper('turpentine/varnish')->getVarnishEnabled()) {
173
            $result = $this->_getVarnishAdmin()->flushUrl('media/(?:js|css)/');
174
            Mage::dispatchEvent('turpentine_ban_media_cache', $result);
175
            $this->_checkResult($result);
176
        }
177
    }
178
179
    /**
180
     * Flush catalog images cache, corresponds to same button in admin cache
181
     * management page
182
     *
183
     * Events:
184
     *     clean_catalog_images_cache_after
185
     *
186
     * @param  Varien_Object $eventObject
187
     * @return null
188
     */
189 View Code Duplication
    public function banCatalogImagesCache($eventObject) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
190
        if (Mage::helper('turpentine/varnish')->getVarnishEnabled()) {
191
            $result = $this->_getVarnishAdmin()->flushUrl(
192
                'media/catalog/product/cache/' );
193
            Mage::dispatchEvent('turpentine_ban_catalog_images_cache', $result);
194
            $this->_checkResult($result);
195
        }
196
    }
197
198
    /**
199
     * Ban a specific CMS page from cache after edit
200
     *
201
     * Events:
202
     *     cms_page_save_commit_after
203
     *
204
     * @param  Varien_Object $eventObject
205
     * @return null
206
     */
207 View Code Duplication
    public function banCmsPageCache($eventObject) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
208
        if (Mage::helper('turpentine/varnish')->getVarnishEnabled()) {
209
            $pageId = $eventObject->getDataObject()->getIdentifier();
210
            $result = $this->_getVarnishAdmin()->flushUrl($pageId.'(?:\.html?)?\/?$');
211
            Mage::dispatchEvent('turpentine_ban_cms_page_cache', $result);
212
            $cronHelper = Mage::helper('turpentine/cron');
213
            if ($this->_checkResult($result) &&
214
                    $cronHelper->getCrawlerEnabled()) {
215
                $cronHelper->addCmsPageToCrawlerQueue($pageId);
216
            }
217
        }
218
    }
219
220
    /**
221
     * Ban a specific CMS page revision from cache after edit (enterprise edition only)
222
     * Events:
223
     *     enterprise_cms_revision_save_commit_after
224
     *
225
     * @param Varien_Object $eventObject
226
     * @return null
227
     */
228
    public function banCmsPageRevisionCache($eventObject) {
229
        if (Mage::helper('turpentine/varnish')->getVarnishEnabled()) {
230
            $pageId = $eventObject->getDataObject()->getPageId();
231
            $page = Mage::getModel('cms/page')->load($pageId);
232
233
            // Don't do anything if the page isn't found.
234
            if ( ! $page) {
235
                return;
236
            }
237
            $pageIdentifier = $page->getIdentifier();
238
            $result = $this->_getVarnishAdmin()->flushUrl($pageIdentifier.'(?:\.html?)?$');
239
            Mage::dispatchEvent('turpentine_ban_cms_page_cache', $result);
240
            $cronHelper = Mage::helper('turpentine/cron');
241
            if ($this->_checkResult($result) &&
242
                $cronHelper->getCrawlerEnabled()) {
243
                $cronHelper->addCmsPageToCrawlerQueue($pageIdentifier);
244
            }
245
        }
246
    }
247
248
    /**
249
     * Do a full cache flush, corresponds to "Flush Magento Cache" and
250
     * "Flush Cache Storage" buttons in admin > cache management
251
     *
252
     * Events:
253
     *     adminhtml_cache_flush_system
254
     *     adminhtml_cache_flush_all
255
     *
256
     * @param  Varien_Object $eventObject
257
     * @return null
258
     */
259 View Code Duplication
    public function banAllCache($eventObject) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
260
        if (Mage::helper('turpentine/varnish')->getVarnishEnabled()) {
261
            $result = $this->_getVarnishAdmin()->flushAll();
262
            Mage::dispatchEvent('turpentine_ban_all_cache', $result);
263
            $this->_checkResult($result);
264
        }
265
    }
266
267
    /**
268
     * Do a flush on the ESI blocks
269
     *
270
     * Events:
271
     *     adminhtml_cache_refresh_type
272
     *
273
     * @param  Varien_Object $eventObject
274
     * @return null
275
     */
276
    public function banCacheType($eventObject) {
277
        switch ($eventObject->getType()) {
278
            //note this is the name of the container xml tag in config.xml,
279
            // **NOT** the cache tag name
280
            case Mage::helper('turpentine/esi')->getMageCacheName():
281
                if (Mage::helper('turpentine/esi')->getEsiEnabled()) {
282
                    $result = $this->_getVarnishAdmin()->flushUrl(
283
                        '/turpentine/esi/getBlock/' );
284
                    Mage::dispatchEvent('turpentine_ban_esi_cache', $result);
285
                    $this->_checkResult($result);
286
                }
287
                break;
288
            case Mage::helper('turpentine/varnish')->getMageCacheName():
289
                $this->banAllCache($eventObject);
290
                break;
291
        }
292
    }
293
294
    /**
295
     * Ban a product's reviews page
296
     *
297
     * @param  Varien_Object $eventObject
298
     * @return bool
299
     */
300
    public function banProductReview($eventObject) {
301
        if (Mage::helper('turpentine/varnish')->getVarnishEnabled()) {
302
            $patterns = array();
303
            /* @var $review \Mage_Review_Model_Review*/
304
            $review = $eventObject->getObject();
305
306
            /* @var $productCollection \Mage_Review_Model_Resource_Review_Product_Collection*/
307
            $productCollection = $review->getProductCollection();
308
309
            $products = $productCollection->addEntityFilter((int) $review->getEntityPkValue())->getItems();
310
311
            $productIds = array_unique(array_map(
312
                create_function('$p', 'return $p->getEntityId();'),
313
                $products ));
314
            $patterns[] = sprintf('/review/product/list/id/(?:%s)/category/',
315
                implode('|', array_unique($productIds)));
316
            $patterns[] = sprintf('/review/product/view/id/%d/',
317
                $review->getEntityId());
318
            $productPatterns = array();
319
            foreach ($products as $p) {
320
                $urlKey = $p->getUrlModel()->formatUrlKey($p->getName());
321
                if ($urlKey) {
322
                    $productPatterns[] = $urlKey;
323
                }
324
            }
325
            if ( ! empty($productPatterns)) {
326
                $productPatterns = array_unique($productPatterns);
327
                $patterns[] = sprintf('(?:%s)', implode('|', $productPatterns));
328
            }
329
            $urlPattern = implode('|', $patterns);
330
331
            $result = $this->_getVarnishAdmin()->flushUrl($urlPattern);
332
            return $this->_checkResult($result);
333
        }
334
    }
335
336
    /**
337
     * Check a result from varnish admin action, log if result has errors
338
     *
339
     * @param  array $result stored as $socketName => $result
340
     * @return bool
341
     */
342
    protected function _checkResult($result) {
343
        $rvalue = true;
344
        foreach ($result as $socketName => $value) {
345
            if ($value !== true) {
346
                Mage::helper('turpentine/debug')->logWarn(
347
                    'Error in Varnish action result for server [%s]: %s',
348
                    $socketName, $value );
349
                $rvalue = false;
350
            }
351
        }
352
        return $rvalue;
353
    }
354
355
    /**
356
     * Get the varnish admin socket
357
     *
358
     * @return Nexcessnet_Turpentine_Model_Varnish_Admin
359
     */
360
    protected function _getVarnishAdmin() {
361
        if (is_null($this->_varnishAdmin)) {
362
            $this->_varnishAdmin = Mage::getModel('turpentine/varnish_admin');
363
        }
364
        return $this->_varnishAdmin;
365
    }
366
}
367