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
|
|
|
* Based heavily on Tim Whitlock's VarnishAdminSocket.php from php-varnish |
24
|
|
|
* @link https://github.com/timwhitlock/php-varnish |
25
|
|
|
* |
26
|
|
|
* Copyright (c) 2010 Tim Whitlock |
27
|
|
|
* |
28
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy |
29
|
|
|
* of this software and associated documentation files (the "Software"), to deal |
30
|
|
|
* in the Software without restriction, including without limitation the rights |
31
|
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
32
|
|
|
* copies of the Software, and to permit persons to whom the Software is |
33
|
|
|
* furnished to do so, subject to the following conditions: |
34
|
|
|
* |
35
|
|
|
* The above copyright notice and this permission notice shall be included in |
36
|
|
|
* all copies or substantial portions of the Software. |
37
|
|
|
* |
38
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
39
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
40
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
41
|
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
42
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
43
|
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
44
|
|
|
* THE SOFTWARE. |
45
|
|
|
*/ |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* @method array help() |
49
|
|
|
* @method array ping() |
50
|
|
|
* @method array auth() |
51
|
|
|
* @method array banner() |
52
|
|
|
* @method array vcl_load() |
53
|
|
|
* @method array vcl_inline() |
54
|
|
|
* @method array vcl_use() |
55
|
|
|
* @method array vcl_discard() |
56
|
|
|
* @method array vcl_list() |
57
|
|
|
* @method array vcl_show() |
58
|
|
|
* @method array param_show() |
59
|
|
|
* @method array param_set() |
60
|
|
|
* Warning: ban_url does a non-lurker-friendly ban. This means it is not cleaned |
61
|
|
|
* up from the ban list. A long ban list will slow down Varnish. |
62
|
|
|
* @method array ban_url() |
63
|
|
|
* @method array ban() |
64
|
|
|
* @method array ban_list() |
65
|
|
|
*/ |
66
|
|
|
class Nexcessnet_Turpentine_Model_Varnish_Admin_Socket { |
67
|
|
|
|
68
|
|
|
// possible command return codes, from vcli.h |
69
|
|
|
const CODE_SYNTAX = 100; |
70
|
|
|
const CODE_UNKNOWN = 101; |
71
|
|
|
const CODE_UNIMPL = 102; |
72
|
|
|
const CODE_TOOFEW = 104; |
73
|
|
|
const CODE_TOOMANY = 105; |
74
|
|
|
const CODE_PARAM = 106; |
75
|
|
|
const CODE_AUTH = 107; |
76
|
|
|
const CODE_OK = 200; |
77
|
|
|
const CODE_CANT = 300; |
78
|
|
|
const CODE_COMMS = 400; |
79
|
|
|
const CODE_CLOSE = 500; |
80
|
|
|
|
81
|
|
|
const READ_CHUNK_SIZE = 1024; |
82
|
|
|
// varnish default, can only be changed at Varnish startup time |
83
|
|
|
// if data to write is over this limit the actual run-time limit is checked |
84
|
|
|
// and used |
85
|
|
|
const CLI_CMD_LENGTH_LIMIT = 16384; |
86
|
|
|
|
87
|
|
|
/** |
88
|
|
|
* Regexp to detect the varnish version number |
89
|
|
|
* @var string |
90
|
|
|
*/ |
91
|
|
|
const REGEXP_VARNISH_VERSION = '/^varnish\-(?P<vmajor>\d+)\.(?P<vminor>\d+)\.(?P<vsub>\d+) revision (?P<vhash>[0-9a-f]+)$/'; |
92
|
|
|
|
93
|
|
|
/** |
94
|
|
|
* VCL config versions, should match config select values |
95
|
|
|
*/ |
96
|
|
|
static protected $_VERSIONS = array('2.1', '3.0', '4.0', '4.1'); |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* Varnish socket connection |
100
|
|
|
* |
101
|
|
|
* @var resource |
102
|
|
|
*/ |
103
|
|
|
protected $_varnishConn = null; |
104
|
|
|
protected $_host = '127.0.0.1'; |
105
|
|
|
protected $_port = 6082; |
106
|
|
|
protected $_private = null; |
107
|
|
|
protected $_authSecret = null; |
108
|
|
|
protected $_timeout = 5; |
109
|
|
|
protected $_version = null; //auto-detect |
110
|
|
|
|
111
|
|
|
public function __construct(array $options = array()) { |
112
|
|
|
foreach ($options as $key => $value) { |
113
|
|
|
switch ($key) { |
114
|
|
|
case 'host': |
115
|
|
|
$this->setHost($value); |
116
|
|
|
break; |
117
|
|
|
case 'port': |
118
|
|
|
$this->setPort($value); |
119
|
|
|
break; |
120
|
|
|
case 'auth_secret': |
121
|
|
|
$this->setAuthSecret($value); |
122
|
|
|
break; |
123
|
|
|
case 'timeout': |
124
|
|
|
$this->setTimeout($value); |
125
|
|
|
break; |
126
|
|
|
case 'version': |
127
|
|
|
$this->setVersion($value); |
128
|
|
|
break; |
129
|
|
|
default: |
130
|
|
|
break; |
131
|
|
|
} |
132
|
|
|
} |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* Provide simple Varnish methods |
137
|
|
|
* |
138
|
|
|
* Methods provided: |
139
|
|
|
help [command] |
140
|
|
|
ping [timestamp] |
141
|
|
|
auth response |
142
|
|
|
banner |
143
|
|
|
stats |
144
|
|
|
vcl.load <configname> <filename> |
145
|
|
|
vcl.inline <configname> <quoted_VCLstring> |
146
|
|
|
vcl.use <configname> |
147
|
|
|
vcl.discard <configname> |
148
|
|
|
vcl.list |
149
|
|
|
vcl.show <configname> |
150
|
|
|
param.show [-l] [<param>] |
151
|
|
|
param.set <param> <value> |
152
|
|
|
purge.url <regexp> |
153
|
|
|
purge <field> <operator> <arg> [&& <field> <oper> <arg>]... |
154
|
|
|
purge.list |
155
|
|
|
* |
156
|
|
|
* @param string $name method name |
157
|
|
|
* @param array $args method args |
158
|
|
|
* @return array |
159
|
|
|
*/ |
160
|
|
|
public function __call($name, $args) { |
161
|
|
|
array_unshift($args, self::CODE_OK); |
162
|
|
|
array_unshift($args, $this->_translateCommandMethod($name)); |
163
|
|
|
return call_user_func_array(array($this, '_command'), $args); |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* Get the connection string for this socket (<host>:<port>) |
168
|
|
|
* |
169
|
|
|
* @return string |
170
|
|
|
*/ |
171
|
|
|
public function getConnectionString() { |
172
|
|
|
return sprintf('%s:%d', $this->getHost(), $this->getPort()); |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* Get the set host for this instance |
177
|
|
|
* |
178
|
|
|
* @return string |
179
|
|
|
*/ |
180
|
|
|
public function getHost() { |
181
|
|
|
return $this->_host; |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
/** |
185
|
|
|
* Set the Varnish host name/ip to connect to |
186
|
|
|
* |
187
|
|
|
* @param string $host hostname or ip |
188
|
|
|
*/ |
189
|
|
|
public function setHost($host) { |
190
|
|
|
$this->_close(); |
191
|
|
|
$this->_host = $host; |
192
|
|
|
return $this; |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
/** |
196
|
|
|
* Get the port set for this instance |
197
|
|
|
* |
198
|
|
|
* @return int |
199
|
|
|
*/ |
200
|
|
|
public function getPort() { |
201
|
|
|
return $this->_port; |
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
/** |
205
|
|
|
* Set the Varnish admin port |
206
|
|
|
* |
207
|
|
|
* @param int $port |
208
|
|
|
*/ |
209
|
|
|
public function setPort($port) { |
210
|
|
|
$this->_close(); |
211
|
|
|
$this->_port = (int) $port; |
212
|
|
|
return $this; |
213
|
|
|
} |
214
|
|
|
|
215
|
|
|
/** |
216
|
|
|
* Set the Varnish admin auth secret, use null to indicate there isn't one |
217
|
|
|
* |
218
|
|
|
* @param string $authSecret |
219
|
|
|
*/ |
220
|
|
|
public function setAuthSecret($authSecret = null) { |
221
|
|
|
$this->_authSecret = $authSecret; |
222
|
|
|
return $this; |
223
|
|
|
} |
224
|
|
|
|
225
|
|
|
/** |
226
|
|
|
* Set the timeout to connect to the varnish instance |
227
|
|
|
* |
228
|
|
|
* @param int $timeout |
229
|
|
|
*/ |
230
|
|
|
public function setTimeout($timeout) { |
231
|
|
|
$this->_timeout = (int) $timeout; |
232
|
|
|
if ( ! is_null($this->_varnishConn)) { |
233
|
|
|
stream_set_timeout($this->_varnishConn, $this->_timeout); |
234
|
|
|
} |
235
|
|
|
return $this; |
236
|
|
|
} |
237
|
|
|
|
238
|
|
|
/** |
239
|
|
|
* Explicitly set the version of the varnish instance we're connecting to |
240
|
|
|
* |
241
|
|
|
* @param string $version version from $_VERSIONS |
242
|
|
|
*/ |
243
|
|
|
public function setVersion($version) { |
244
|
|
|
if (in_array($version, self::$_VERSIONS)) { |
245
|
|
|
$this->_version = $version; |
246
|
|
|
} else { |
247
|
|
|
Mage::throwException('Unsupported Varnish version: '.$version); |
248
|
|
|
} |
249
|
|
|
} |
250
|
|
|
|
251
|
|
|
/** |
252
|
|
|
* Check if we're connected to Varnish |
253
|
|
|
* |
254
|
|
|
* @return boolean |
255
|
|
|
*/ |
256
|
|
|
public function isConnected() { |
257
|
|
|
return ! is_null($this->_varnishConn); |
258
|
|
|
} |
259
|
|
|
|
260
|
|
|
/** |
261
|
|
|
* Find out what version mode we're running in |
262
|
|
|
* |
263
|
|
|
* @return string |
264
|
|
|
*/ |
265
|
|
|
public function getVersion() { |
266
|
|
|
if ( ! $this->isConnected()) { |
267
|
|
|
$this->_connect(); |
268
|
|
|
} |
269
|
|
|
return $this->_version; |
270
|
|
|
} |
271
|
|
|
|
272
|
|
|
/** |
273
|
|
|
* Stop the Varnish instance |
274
|
|
|
*/ |
275
|
|
|
public function quit() { |
276
|
|
|
$this->_command('quit', self::CODE_CLOSE); |
277
|
|
|
$this->_close(); |
278
|
|
|
} |
279
|
|
|
|
280
|
|
|
/** |
281
|
|
|
* Check if Varnish has a child running or not |
282
|
|
|
* |
283
|
|
|
* @return boolean |
284
|
|
|
*/ |
285
|
|
|
public function status() { |
286
|
|
|
$response = $this->_command('status'); |
287
|
|
|
if ( ! preg_match('~Child in state (\w+)~', $response['text'], $match)) { |
288
|
|
|
return false; |
289
|
|
|
} else { |
290
|
|
|
return $match[1] === 'running'; |
291
|
|
|
} |
292
|
|
|
} |
293
|
|
|
|
294
|
|
|
/** |
295
|
|
|
* Stop the running child (if it is running) |
296
|
|
|
* |
297
|
|
|
* @return $this |
298
|
|
|
*/ |
299
|
|
|
public function stop() { |
300
|
|
|
if ($this->status()) { |
301
|
|
|
$this->_command('stop'); |
302
|
|
|
} |
303
|
|
|
return $this; |
304
|
|
|
} |
305
|
|
|
|
306
|
|
|
/** |
307
|
|
|
* Start running the Varnish child |
308
|
|
|
* |
309
|
|
|
* @return $this |
310
|
|
|
*/ |
311
|
|
|
public function start() { |
312
|
|
|
$this->_command('start'); |
313
|
|
|
return $this; |
314
|
|
|
} |
315
|
|
|
|
316
|
|
|
/** |
317
|
|
|
* Establish a connection to the configured Varnish instance |
318
|
|
|
* |
319
|
|
|
* @return boolean |
320
|
|
|
*/ |
321
|
|
|
protected function _connect() { |
322
|
|
|
$this->_varnishConn = fsockopen($this->_host, $this->_port, $errno, |
323
|
|
|
$errstr, $this->_timeout); |
324
|
|
|
if ( ! is_resource($this->_varnishConn)) { |
325
|
|
|
Mage::throwException(sprintf( |
326
|
|
|
'Failed to connect to Varnish on [%s:%d]: (%d) %s', |
327
|
|
|
$this->_host, $this->_port, $errno, $errstr )); |
328
|
|
|
} |
329
|
|
|
|
330
|
|
|
stream_set_blocking($this->_varnishConn, 1); |
331
|
|
|
stream_set_timeout($this->_varnishConn, $this->_timeout); |
332
|
|
|
|
333
|
|
|
//varnish 2.0 doesn't spit out a banner on connection, this will need |
334
|
|
|
//to be changed if 2.0 support is ever added |
335
|
|
|
$banner = $this->_read(); |
336
|
|
|
if ($banner['code'] === self::CODE_AUTH) { |
337
|
|
|
$challenge = substr($banner['text'], 0, 32); |
338
|
|
|
$response = hash('sha256', sprintf("%s\n%s%s\n", $challenge, |
339
|
|
|
$this->_authSecret, $challenge)); |
340
|
|
|
$banner = $this->_command('auth', self::CODE_OK, $response); |
341
|
|
|
} |
342
|
|
|
|
343
|
|
|
if ($banner['code'] !== self::CODE_OK) { |
344
|
|
|
Mage::throwException('Varnish admin authentication failed: '. |
345
|
|
|
$banner['text']); |
346
|
|
|
} |
347
|
|
|
|
348
|
|
|
if ($this->_version == null) { // If autodetecting |
349
|
|
|
$this->_version = $this->_determineVersion($banner['text']); |
350
|
|
|
} |
351
|
|
|
|
352
|
|
|
return $this->isConnected(); |
353
|
|
|
} |
354
|
|
|
|
355
|
|
|
/** |
356
|
|
|
* @param string $bannerText |
357
|
|
|
*/ |
358
|
|
|
protected function _determineVersion($bannerText) { |
359
|
|
|
$bannerText = array_filter(explode("\n", $bannerText)); |
360
|
|
|
if (count($bannerText) < 6) { |
361
|
|
|
// Varnish 2.0 does not spit out a banner on connect |
362
|
|
|
Mage::throwException('Varnish versions before 2.1 are not supported'); |
363
|
|
|
} |
364
|
|
|
if (count($bannerText) < 7) { |
365
|
|
|
// Varnish before 3.0.4 does not spit out a version number |
366
|
|
|
$resp = $this->_write('help')->_read(); |
367
|
|
|
if (strpos($resp['text'], 'ban.url') !== false) { |
368
|
|
|
// Varnish versions 3.0 through 3.0.3 do not return a version banner. |
369
|
|
|
// To differentiate between 2.1 and 3.0, we check the existence of the ban.url command. |
370
|
|
|
return '3.0'; |
371
|
|
|
} |
372
|
|
|
return '2.1'; |
373
|
|
|
} elseif (preg_match(self::REGEXP_VARNISH_VERSION, $bannerText[4], $matches) === 1) { |
374
|
|
|
return $matches['vmajor'].'.'.$matches['vminor']; |
375
|
|
|
} else { |
376
|
|
|
Mage::throwException('Unable to detect varnish version'); |
377
|
|
|
} |
378
|
|
|
} |
379
|
|
|
|
380
|
|
|
/** |
381
|
|
|
* Close the connection (if we're connected) |
382
|
|
|
* |
383
|
|
|
* @return $this |
384
|
|
|
*/ |
385
|
|
|
protected function _close() { |
386
|
|
|
if ($this->isConnected()) { |
387
|
|
|
fclose($this->_varnishConn); |
388
|
|
|
$this->_varnishConn = null; |
389
|
|
|
} |
390
|
|
|
return $this; |
391
|
|
|
} |
392
|
|
|
|
393
|
|
|
/** |
394
|
|
|
* Write data to the Varnish instance, a newline is automatically appended |
395
|
|
|
* |
396
|
|
|
* @param string $data data to write |
397
|
|
|
* @return $this |
398
|
|
|
*/ |
399
|
|
|
protected function _write($data) { |
400
|
|
|
if (is_null($this->_varnishConn)) { |
401
|
|
|
$this->_connect(); |
402
|
|
|
} |
403
|
|
|
$data = rtrim($data).PHP_EOL; |
404
|
|
|
$dataLength = strlen($data); |
405
|
|
|
if ($dataLength >= self::CLI_CMD_LENGTH_LIMIT) { |
406
|
|
|
$cliBufferResponse = $this->param_show('cli_buffer'); |
|
|
|
|
407
|
|
|
$regexp = '~^cli_buffer\s+(\d+)\s+\[bytes\]~'; |
408
|
|
|
if ($this->getVersion() === '4.0' || $this->getVersion() === '4.1') { |
409
|
|
|
// Varnish4 supports "16k" style notation |
410
|
|
|
$regexp = '~^cli_buffer\s+Value is:\s+(\d+)([k|m|g|b]{1})?\s+\[bytes\]~'; |
411
|
|
|
} |
412
|
|
|
if (preg_match($regexp, $cliBufferResponse['text'], $match)) { |
413
|
|
|
$realLimit = (int) $match[1]; |
414
|
|
|
if (isset($match[2])) { |
415
|
|
|
$factors = array('b'=>0, 'k'=>1, 'm'=>2, 'g'=>3); |
416
|
|
|
$realLimit *= pow(1024, $factors[$match[2]]); |
417
|
|
|
} |
418
|
|
|
} else { |
419
|
|
|
Mage::helper('turpentine/debug')->logWarn( |
420
|
|
|
'Failed to determine Varnish cli_buffer limit, using default' ); |
421
|
|
|
$realLimit = self::CLI_CMD_LENGTH_LIMIT; |
422
|
|
|
} |
423
|
|
|
if ($dataLength >= $realLimit) { |
424
|
|
|
Mage::throwException(sprintf( |
425
|
|
|
'Varnish data to write over length limit by %d characters', |
426
|
|
|
$dataLength - $realLimit )); |
427
|
|
|
} |
428
|
|
|
} |
429
|
|
|
if (($byteCount = fwrite($this->_varnishConn, $data)) !== $dataLength) { |
430
|
|
|
Mage::throwException(sprintf('Varnish socket write error: %d != %d', |
431
|
|
|
$byteCount, $dataLength)); |
432
|
|
|
} |
433
|
|
|
return $this; |
434
|
|
|
} |
435
|
|
|
|
436
|
|
|
/** |
437
|
|
|
* Read a response from Varnish instance |
438
|
|
|
* |
439
|
|
|
* @return array tuple of the response (code, text) |
440
|
|
|
*/ |
441
|
|
|
protected function _read() { |
442
|
|
|
$code = null; |
443
|
|
|
$len = -1; |
444
|
|
|
while ( ! feof($this->_varnishConn)) { |
445
|
|
|
$response = fgets($this->_varnishConn, self::READ_CHUNK_SIZE); |
446
|
|
|
if (empty($response)) { |
447
|
|
|
$streamMeta = stream_get_meta_data($this->_varnishConn); |
448
|
|
|
if ($streamMeta['timed_out']) { |
449
|
|
|
Mage::throwException('Varnish admin socket timeout'); |
450
|
|
|
} |
451
|
|
|
} |
452
|
|
|
if (preg_match('~^(\d{3}) (\d+)~', $response, $match)) { |
453
|
|
|
$code = (int) $match[1]; |
454
|
|
|
$len = (int) $match[2]; |
455
|
|
|
break; |
456
|
|
|
} |
457
|
|
|
} |
458
|
|
|
|
459
|
|
|
if (is_null($code)) { |
460
|
|
|
Mage::throwException('Failed to read response code from Varnish'); |
461
|
|
|
} else { |
462
|
|
|
$response = array('code' => $code, 'text' => ''); |
463
|
|
|
while ( ! feof($this->_varnishConn) && |
464
|
|
|
strlen($response['text']) < $len) { |
465
|
|
|
$response['text'] .= fgets($this->_varnishConn, |
466
|
|
|
self::READ_CHUNK_SIZE); |
467
|
|
|
} |
468
|
|
|
return $response; |
469
|
|
|
} |
470
|
|
|
} |
471
|
|
|
|
472
|
|
|
/** |
473
|
|
|
* [_command description] |
474
|
|
|
* @param string $verb command name |
475
|
|
|
* @param integer $okCode code that indicates command was successful |
476
|
|
|
* @param string ... command args |
477
|
|
|
* @return array |
478
|
|
|
*/ |
479
|
|
|
protected function _command($verb, $okCode = 200) { |
480
|
|
|
$params = func_get_args(); |
481
|
|
|
//remove $verb |
482
|
|
|
array_shift($params); |
483
|
|
|
//remove $okCode (if it exists) |
484
|
|
|
array_shift($params); |
485
|
|
|
$cleanedParams = array(); |
486
|
|
|
foreach ($params as $param) { |
487
|
|
|
$cp = addcslashes($param, "\"\\"); |
488
|
|
|
$cp = str_replace(PHP_EOL, '\n', $cp); |
489
|
|
|
$cleanedParams[] = sprintf('"%s"', $cp); |
490
|
|
|
} |
491
|
|
|
$data = implode(' ', array_merge( |
492
|
|
|
array(sprintf('"%s"', $verb)), |
493
|
|
|
$cleanedParams )); |
494
|
|
|
$response = $this->_write($data)->_read(); |
495
|
|
|
if ($response['code'] !== $okCode && ! is_null($okCode)) { |
496
|
|
|
Mage::helper('turpentine/debug')->logDebug( |
497
|
|
|
'Error on Varnish command: %s', $data ); |
498
|
|
|
Mage::throwException(sprintf( |
499
|
|
|
"Got unexpected response code from Varnish: %d\n%s", |
500
|
|
|
$response['code'], $response['text'] )); |
501
|
|
|
} else { |
502
|
|
|
if (Mage::getStoreConfig('turpentine_varnish/general/varnish_log_commands')) { |
503
|
|
|
Mage::helper('turpentine/debug')->logDebug('VARNISH command sent: '.$data); |
504
|
|
|
} |
505
|
|
|
return $response; |
506
|
|
|
} |
507
|
|
|
} |
508
|
|
|
|
509
|
|
|
/** |
510
|
|
|
* Handle v2.1 <> v3.0 command compatibility |
511
|
|
|
* |
512
|
|
|
* @param string $verb command to check |
513
|
|
|
* @return string |
514
|
|
|
*/ |
515
|
|
|
protected function _translateCommandMethod($verb) { |
516
|
|
|
$command = str_replace('_', '.', $verb); |
517
|
|
|
switch ($this->getVersion()) { |
518
|
|
|
case '2.1': |
519
|
|
|
$command = str_replace('ban', 'purge', $command); |
520
|
|
|
break; |
521
|
|
|
case '4.1': |
522
|
|
|
case '4.0': |
523
|
|
|
case '3.0': |
524
|
|
|
$command = str_replace('purge', 'ban', $command); |
525
|
|
|
break; |
526
|
|
|
default: |
527
|
|
|
Mage::throwException('Unrecognized Varnish version: '. |
528
|
|
|
$this->_version); |
529
|
|
|
} |
530
|
|
|
return $command; |
531
|
|
|
} |
532
|
|
|
} |
533
|
|
|
|
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.