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
|
|
|
class Nexcessnet_Turpentine_Model_Varnish_Admin { |
23
|
|
|
|
24
|
|
|
const MASK_ESI_SYNTAX = 0x2; |
25
|
|
|
const URL_ESI_SYNTAX_FIX = 'https://github.com/nexcess/magento-turpentine/wiki/FAQ#wiki-i-upgraded-to-turpentine-06-and-are-the-add-to-cart-buttons-look-broken'; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* Flush all Magento URLs in Varnish cache |
29
|
|
|
* |
30
|
|
|
* @return bool |
31
|
|
|
*/ |
32
|
|
|
public function flushAll() { |
33
|
|
|
return $this->flushUrl('.*'); |
34
|
|
|
} |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* Flush all Magento URLs matching the given (relative) regex |
38
|
|
|
* |
39
|
|
|
* @param string $subPattern regex to match against URLs |
40
|
|
|
* @return bool |
41
|
|
|
*/ |
42
|
|
|
public function flushUrl($subPattern) { |
43
|
|
|
$result = array(); |
44
|
|
View Code Duplication |
foreach (Mage::helper('turpentine/varnish')->getSockets() as $socket) { |
|
|
|
|
45
|
|
|
$socketName = $socket->getConnectionString(); |
46
|
|
|
try { |
47
|
|
|
// We don't use "ban_url" here, because we want to do lurker friendly bans. |
48
|
|
|
// Lurker friendly bans get cleaned up, so they don't slow down Varnish. |
49
|
|
|
$socket->ban('obj.http.X-Varnish-URL', '~', $subPattern); |
50
|
|
|
} catch (Mage_Core_Exception $e) { |
51
|
|
|
$result[$socketName] = $e->getMessage(); |
52
|
|
|
continue; |
53
|
|
|
} |
54
|
|
|
$result[$socketName] = true; |
55
|
|
|
} |
56
|
|
|
return $result; |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* Flush according to Varnish expression |
61
|
|
|
* |
62
|
|
|
* @param mixed ... |
63
|
|
|
* @return array |
64
|
|
|
*/ |
65
|
|
|
public function flushExpression() { |
66
|
|
|
$args = func_get_args(); |
67
|
|
|
$result = array(); |
68
|
|
View Code Duplication |
foreach (Mage::helper('turpentine/varnish')->getSockets() as $socket) { |
|
|
|
|
69
|
|
|
$socketName = $socket->getConnectionString(); |
70
|
|
|
try { |
71
|
|
|
call_user_func_array(array($socket, 'ban'), $args); |
72
|
|
|
} catch (Mage_Core_Exception $e) { |
73
|
|
|
$result[$socketName] = $e->getMessage(); |
74
|
|
|
continue; |
75
|
|
|
} |
76
|
|
|
$result[$socketName] = true; |
77
|
|
|
} |
78
|
|
|
return $result; |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
/** |
82
|
|
|
* Flush all cached objects with the given content type |
83
|
|
|
* |
84
|
|
|
* @param string $contentType |
85
|
|
|
* @return array |
86
|
|
|
*/ |
87
|
|
|
public function flushContentType($contentType) { |
88
|
|
|
return $this->flushExpression( |
89
|
|
|
'obj.http.Content-Type', '~', $contentType ); |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* Generate and apply the config to the Varnish instances |
94
|
|
|
* |
95
|
|
|
* @return bool |
96
|
|
|
*/ |
97
|
|
|
public function applyConfig() { |
98
|
|
|
$result = array(); |
99
|
|
|
$helper = Mage::helper('turpentine'); |
100
|
|
|
foreach (Mage::helper('turpentine/varnish')->getSockets() as $socket) { |
101
|
|
|
$cfgr = Nexcessnet_Turpentine_Model_Varnish_Configurator_Abstract::getFromSocket($socket); |
102
|
|
|
$socketName = $socket->getConnectionString(); |
103
|
|
|
if (is_null($cfgr)) { |
104
|
|
|
$result[$socketName] = 'Failed to load configurator'; |
105
|
|
|
} else { |
106
|
|
|
$vcl = $cfgr->generate($helper->shouldStripVclWhitespace('apply')); |
107
|
|
|
$vclName = 'vcl_' . Mage::helper('turpentine/data') |
108
|
|
|
->secureHash(microtime()); |
109
|
|
|
try { |
110
|
|
|
$this->_testEsiSyntaxParam($socket); |
111
|
|
|
$socket->vcl_inline($vclName, $vcl); |
112
|
|
|
sleep(1); //this is probably not really needed |
113
|
|
|
$socket->vcl_use($vclName); |
114
|
|
|
} catch (Mage_Core_Exception $e) { |
115
|
|
|
$result[$socketName] = $e->getMessage(); |
116
|
|
|
continue; |
117
|
|
|
} |
118
|
|
|
$result[$socketName] = true; |
119
|
|
|
} |
120
|
|
|
} |
121
|
|
|
return $result; |
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
/** |
125
|
|
|
* Get a configurator based on the first socket in the server list |
126
|
|
|
* |
127
|
|
|
* @return Nexcessnet_Turpentine_Model_Varnish_Configurator_Abstract |
128
|
|
|
*/ |
129
|
|
|
public function getConfigurator() { |
130
|
|
|
$sockets = Mage::helper('turpentine/varnish')->getSockets(); |
131
|
|
|
$cfgr = Nexcessnet_Turpentine_Model_Varnish_Configurator_Abstract::getFromSocket($sockets[0]); |
132
|
|
|
return $cfgr; |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
protected function _testEsiSyntaxParam($socket) { |
136
|
|
|
$session = Mage::getSingleton('adminhtml/session'); |
137
|
|
|
$helper = Mage::helper('turpentine/varnish'); |
138
|
|
|
$result = false; |
139
|
|
|
|
140
|
|
|
if ($helper->csrfFixupNeeded()) { |
141
|
|
|
if ($socket->getVersion() === '4.0' || $socket->getVersion() === '4.1') { |
142
|
|
|
$paramName = 'feature'; |
143
|
|
|
$value = $socket->param_show($paramName); |
144
|
|
|
$value = explode("\n", $value['text']); |
145
|
|
|
if (isset($value[1]) && strpos($value[1], '+esi_ignore_other_elements') !== false) { |
146
|
|
|
$result = true; |
147
|
|
|
} else { |
148
|
|
|
$session->addWarning('Varnish <em>feature</em> param is '. |
149
|
|
|
'not set correctly, please see <a target="_blank" href="'. |
150
|
|
|
self::URL_ESI_SYNTAX_FIX.'">these instructions</a> '. |
151
|
|
|
'to fix this warning.'); |
152
|
|
|
} |
153
|
|
|
} else { |
154
|
|
|
$paramName = 'esi_syntax'; |
155
|
|
|
$value = $socket->param_show($paramName); |
156
|
|
|
if (preg_match('~(\d)\s+\[bitmap\]~', $value['text'], $match)) { |
157
|
|
|
$value = hexdec($match[1]); |
158
|
|
|
if ($value & self::MASK_ESI_SYNTAX) { //bitwise intentional |
159
|
|
|
// setting is correct, all is fine |
160
|
|
|
$result = true; |
161
|
|
|
} else { |
162
|
|
|
$session->addWarning('Varnish <em>esi_syntax</em> param is '. |
163
|
|
|
'not set correctly, please see <a target="_blank" href="'. |
164
|
|
|
self::URL_ESI_SYNTAX_FIX.'">these instructions</a> '. |
165
|
|
|
'to fix this warning.'); |
166
|
|
|
} |
167
|
|
|
} |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
if ($result === false) { |
171
|
|
|
// error |
172
|
|
|
Mage::helper('turpentine/debug')->logWarn( |
173
|
|
|
sprintf('Failed to parse param.show output to check %s value', $paramName) ); |
174
|
|
|
$result = true; |
175
|
|
|
} |
176
|
|
|
} else { |
177
|
|
|
$result = true; |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
return $result; |
181
|
|
|
} |
182
|
|
|
} |
183
|
|
|
|
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.