正在显示
56 个修改的文件
包含
4425 行增加
和
138 行删除
@@ -8,7 +8,8 @@ use app\common\model\Version; | @@ -8,7 +8,8 @@ use app\common\model\Version; | ||
8 | use Qiniu\Auth; | 8 | use Qiniu\Auth; |
9 | use think\Config; | 9 | use think\Config; |
10 | use think\Hook; | 10 | use think\Hook; |
11 | -use EasyWeChat\Factory; | 11 | +//use EasyWeChat\Factory; |
12 | +use EasyWeChat\Foundation\Application; | ||
12 | use think\Db; | 13 | use think\Db; |
13 | use app\common\model\Attachment; | 14 | use app\common\model\Attachment; |
14 | use think\process\exception\Timeout; | 15 | use think\process\exception\Timeout; |
@@ -429,9 +430,10 @@ class Common extends Api | @@ -429,9 +430,10 @@ class Common extends Api | ||
429 | 'key_path' => '/home/wwwroot/fast/book/addons/epay/certs/apiclient_key.pem', // XXX: 绝对路径!!!! | 430 | 'key_path' => '/home/wwwroot/fast/book/addons/epay/certs/apiclient_key.pem', // XXX: 绝对路径!!!! |
430 | ], | 431 | ], |
431 | ]; | 432 | ]; |
432 | - $app = Factory::officialAccount($config); | 433 | + $app = new Application($config); |
434 | + $payment = $app->payment; | ||
433 | try { | 435 | try { |
434 | - $result = $app->refund->byTransactionId($PayOrderInfo['WeChatOrder'], $PayOrderInfo['PayOrder'], $PayOrderInfo['money'] * 100, $TuiMoney * 100); // 总金额 100, 退款 80,操作员:商户号 | 436 | + $result = $payment->refundByTransactionId($PayOrderInfo['WeChatOrder'], $PayOrderInfo['PayOrder'], $PayOrderInfo['money'] * 100, $TuiMoney * 100); // 总金额 100, 退款 80,操作员:商户号 |
435 | //更改订单状态为已退款 | 437 | //更改订单状态为已退款 |
436 | Db::name('pay_order')->where('OrderSn', $OrderSn['OrderSn'])->where('PayOrder', $PayOrderInfo['PayOrder'])->update(['type' => 0]); | 438 | Db::name('pay_order')->where('OrderSn', $OrderSn['OrderSn'])->where('PayOrder', $PayOrderInfo['PayOrder'])->update(['type' => 0]); |
437 | } catch (Exception $e) { | 439 | } catch (Exception $e) { |
@@ -512,9 +514,10 @@ class Common extends Api | @@ -512,9 +514,10 @@ class Common extends Api | ||
512 | 'key_path' => '/home/wwwroot/fast/book/addons/epay/certs/apiclient_key.pem', // XXX: 绝对路径!!!! | 514 | 'key_path' => '/home/wwwroot/fast/book/addons/epay/certs/apiclient_key.pem', // XXX: 绝对路径!!!! |
513 | ], | 515 | ], |
514 | ]; | 516 | ]; |
515 | - $app = Factory::officialAccount($config); | 517 | + $app = new Application($config); |
518 | + $payment = $app->payment; | ||
516 | try { | 519 | try { |
517 | - $result = $app->refund->byTransactionId($PayOrderInfo['WeChatOrder'], $PayOrderInfo['PayOrder'], $PayOrderInfo['money'] * 100, $TuiMoney * 100); // 总金额 100, 退款 80,操作员:商户号 | 520 | + $result = $payment->refundByTransactionId($PayOrderInfo['WeChatOrder'], $PayOrderInfo['PayOrder'], $PayOrderInfo['money'] * 100, $TuiMoney * 100); // 总金额 100, 退款 80,操作员:商户号 |
518 | //更改订单状态为已退款 | 521 | //更改订单状态为已退款 |
519 | Db::name('pay_order')->where('OrderSn', $OrderSn)->where('PayOrder', $PayOrderInfo['PayOrder'])->update(['type' => 0]); | 522 | Db::name('pay_order')->where('OrderSn', $OrderSn)->where('PayOrder', $PayOrderInfo['PayOrder'])->update(['type' => 0]); |
520 | } catch (Exception $e) { | 523 | } catch (Exception $e) { |
@@ -22,12 +22,12 @@ | @@ -22,12 +22,12 @@ | ||
22 | "karsonzhang/fastadmin-addons": "~1.2.4", | 22 | "karsonzhang/fastadmin-addons": "~1.2.4", |
23 | "overtrue/pinyin": "~3.0", | 23 | "overtrue/pinyin": "~3.0", |
24 | "phpoffice/phpspreadsheet": "^1.2", | 24 | "phpoffice/phpspreadsheet": "^1.2", |
25 | - "overtrue/wechat": "4.2.11", | ||
26 | "nelexa/zip": "^3.3", | 25 | "nelexa/zip": "^3.3", |
27 | "symfony/var-exporter": "^4.4.13", | 26 | "symfony/var-exporter": "^4.4.13", |
28 | "ext-json": "*", | 27 | "ext-json": "*", |
29 | "ext-curl": "*", | 28 | "ext-curl": "*", |
30 | - "ext-pdo": "*" | 29 | + "ext-pdo": "*", |
30 | + "overtrue/wechat": "~3.1" | ||
31 | }, | 31 | }, |
32 | "config": { | 32 | "config": { |
33 | "preferred-install": "dist" | 33 | "preferred-install": "dist" |
@@ -2,6 +2,6 @@ | @@ -2,6 +2,6 @@ | ||
2 | 2 | ||
3 | // autoload.php @generated by Composer | 3 | // autoload.php @generated by Composer |
4 | 4 | ||
5 | -require_once __DIR__ . '/composer' . '/autoload_real.php'; | 5 | +require_once __DIR__ . '/composer/autoload_real.php'; |
6 | 6 | ||
7 | return ComposerAutoloaderInitf00349b72964a05454b796bb539364c1::getLoader(); | 7 | return ComposerAutoloaderInitf00349b72964a05454b796bb539364c1::getLoader(); |
@@ -55,6 +55,7 @@ class ClassLoader | @@ -55,6 +55,7 @@ class ClassLoader | ||
55 | private $classMap = array(); | 55 | private $classMap = array(); |
56 | private $classMapAuthoritative = false; | 56 | private $classMapAuthoritative = false; |
57 | private $missingClasses = array(); | 57 | private $missingClasses = array(); |
58 | + private $apcuPrefix; | ||
58 | 59 | ||
59 | public function getPrefixes() | 60 | public function getPrefixes() |
60 | { | 61 | { |
@@ -272,6 +273,26 @@ class ClassLoader | @@ -272,6 +273,26 @@ class ClassLoader | ||
272 | } | 273 | } |
273 | 274 | ||
274 | /** | 275 | /** |
276 | + * APCu prefix to use to cache found/not-found classes, if the extension is enabled. | ||
277 | + * | ||
278 | + * @param string|null $apcuPrefix | ||
279 | + */ | ||
280 | + public function setApcuPrefix($apcuPrefix) | ||
281 | + { | ||
282 | + $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; | ||
283 | + } | ||
284 | + | ||
285 | + /** | ||
286 | + * The APCu prefix in use, or null if APCu caching is not enabled. | ||
287 | + * | ||
288 | + * @return string|null | ||
289 | + */ | ||
290 | + public function getApcuPrefix() | ||
291 | + { | ||
292 | + return $this->apcuPrefix; | ||
293 | + } | ||
294 | + | ||
295 | + /** | ||
275 | * Registers this instance as an autoloader. | 296 | * Registers this instance as an autoloader. |
276 | * | 297 | * |
277 | * @param bool $prepend Whether to prepend the autoloader or not | 298 | * @param bool $prepend Whether to prepend the autoloader or not |
@@ -313,11 +334,6 @@ class ClassLoader | @@ -313,11 +334,6 @@ class ClassLoader | ||
313 | */ | 334 | */ |
314 | public function findFile($class) | 335 | public function findFile($class) |
315 | { | 336 | { |
316 | - // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731 | ||
317 | - if ('\\' == $class[0]) { | ||
318 | - $class = substr($class, 1); | ||
319 | - } | ||
320 | - | ||
321 | // class map lookup | 337 | // class map lookup |
322 | if (isset($this->classMap[$class])) { | 338 | if (isset($this->classMap[$class])) { |
323 | return $this->classMap[$class]; | 339 | return $this->classMap[$class]; |
@@ -325,6 +341,12 @@ class ClassLoader | @@ -325,6 +341,12 @@ class ClassLoader | ||
325 | if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { | 341 | if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { |
326 | return false; | 342 | return false; |
327 | } | 343 | } |
344 | + if (null !== $this->apcuPrefix) { | ||
345 | + $file = apcu_fetch($this->apcuPrefix.$class, $hit); | ||
346 | + if ($hit) { | ||
347 | + return $file; | ||
348 | + } | ||
349 | + } | ||
328 | 350 | ||
329 | $file = $this->findFileWithExtension($class, '.php'); | 351 | $file = $this->findFileWithExtension($class, '.php'); |
330 | 352 | ||
@@ -333,6 +355,10 @@ class ClassLoader | @@ -333,6 +355,10 @@ class ClassLoader | ||
333 | $file = $this->findFileWithExtension($class, '.hh'); | 355 | $file = $this->findFileWithExtension($class, '.hh'); |
334 | } | 356 | } |
335 | 357 | ||
358 | + if (null !== $this->apcuPrefix) { | ||
359 | + apcu_add($this->apcuPrefix.$class, $file); | ||
360 | + } | ||
361 | + | ||
336 | if (false === $file) { | 362 | if (false === $file) { |
337 | // Remember that this class does not exist. | 363 | // Remember that this class does not exist. |
338 | $this->missingClasses[$class] = true; | 364 | $this->missingClasses[$class] = true; |
@@ -348,10 +374,14 @@ class ClassLoader | @@ -348,10 +374,14 @@ class ClassLoader | ||
348 | 374 | ||
349 | $first = $class[0]; | 375 | $first = $class[0]; |
350 | if (isset($this->prefixLengthsPsr4[$first])) { | 376 | if (isset($this->prefixLengthsPsr4[$first])) { |
351 | - foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { | ||
352 | - if (0 === strpos($class, $prefix)) { | ||
353 | - foreach ($this->prefixDirsPsr4[$prefix] as $dir) { | ||
354 | - if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { | 377 | + $subPath = $class; |
378 | + while (false !== $lastPos = strrpos($subPath, '\\')) { | ||
379 | + $subPath = substr($subPath, 0, $lastPos); | ||
380 | + $search = $subPath . '\\'; | ||
381 | + if (isset($this->prefixDirsPsr4[$search])) { | ||
382 | + $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); | ||
383 | + foreach ($this->prefixDirsPsr4[$search] as $dir) { | ||
384 | + if (file_exists($file = $dir . $pathEnd)) { | ||
355 | return $file; | 385 | return $file; |
356 | } | 386 | } |
357 | } | 387 | } |
1 | 1 | ||
2 | -Copyright (c) 2016 Nils Adermann, Jordi Boggiano | 2 | +Copyright (c) Nils Adermann, Jordi Boggiano |
3 | 3 | ||
4 | Permission is hereby granted, free of charge, to any person obtaining a copy | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy |
5 | of this software and associated documentation files (the "Software"), to deal | 5 | of this software and associated documentation files (the "Software"), to deal |
@@ -6,12 +6,5 @@ $vendorDir = dirname(dirname(__FILE__)); | @@ -6,12 +6,5 @@ $vendorDir = dirname(dirname(__FILE__)); | ||
6 | $baseDir = dirname($vendorDir); | 6 | $baseDir = dirname($vendorDir); |
7 | 7 | ||
8 | return array( | 8 | return array( |
9 | - 'ArithmeticError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/ArithmeticError.php', | ||
10 | - 'AssertionError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/AssertionError.php', | ||
11 | - 'DivisionByZeroError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/DivisionByZeroError.php', | ||
12 | - 'Error' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/Error.php', | ||
13 | 'Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php', | 9 | 'Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php', |
14 | - 'ParseError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/ParseError.php', | ||
15 | - 'SessionUpdateTimestampHandlerInterface' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/SessionUpdateTimestampHandlerInterface.php', | ||
16 | - 'TypeError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/TypeError.php', | ||
17 | ); | 10 | ); |
@@ -6,31 +6,14 @@ $vendorDir = dirname(dirname(__FILE__)); | @@ -6,31 +6,14 @@ $vendorDir = dirname(dirname(__FILE__)); | ||
6 | $baseDir = dirname($vendorDir); | 6 | $baseDir = dirname($vendorDir); |
7 | 7 | ||
8 | return array( | 8 | return array( |
9 | - '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', | ||
10 | - '25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php', | ||
11 | - '023d27dca8066ef29e6739335ea73bad' => $vendorDir . '/symfony/polyfill-php70/bootstrap.php', | ||
12 | - 'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php', | ||
13 | - 'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php', | ||
14 | '7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php', | 9 | '7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php', |
15 | 'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php', | 10 | 'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php', |
11 | + '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', | ||
12 | + 'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php', | ||
13 | + '25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php', | ||
16 | 'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php', | 14 | 'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php', |
15 | + 'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php', | ||
17 | '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php', | 16 | '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php', |
18 | - '9d8e013a5160a09477beb8e44f8ae97b' => $vendorDir . '/markbaker/matrix/classes/src/functions/adjoint.php', | ||
19 | - '6e78d1bdea6248d6aa117229efae50f2' => $vendorDir . '/markbaker/matrix/classes/src/functions/antidiagonal.php', | ||
20 | - '4623d87924d94f5412fe5afbf1cef31d' => $vendorDir . '/markbaker/matrix/classes/src/functions/cofactors.php', | ||
21 | - '901fd1f6950a637ca85f66b701a45e13' => $vendorDir . '/markbaker/matrix/classes/src/functions/determinant.php', | ||
22 | - '83057abc0e4acc99ba80154ee5d02a49' => $vendorDir . '/markbaker/matrix/classes/src/functions/diagonal.php', | ||
23 | - '07b7fd7a434451149b4fd477fca0ce06' => $vendorDir . '/markbaker/matrix/classes/src/functions/identity.php', | ||
24 | - 'c8d43b340583e07ae89f2a3baef2cf89' => $vendorDir . '/markbaker/matrix/classes/src/functions/inverse.php', | ||
25 | - '499bb10ed7a3aee2ba4c09a31a85e8d1' => $vendorDir . '/markbaker/matrix/classes/src/functions/minors.php', | ||
26 | - '1cad2e6414d652e8b1c64e8967f6f37d' => $vendorDir . '/markbaker/matrix/classes/src/functions/trace.php', | ||
27 | - '95a7f134ac17161d07def442b3b737e8' => $vendorDir . '/markbaker/matrix/classes/src/functions/transpose.php', | ||
28 | - 'b3a6bc628377118d4b4b8ba08d1eb949' => $vendorDir . '/markbaker/matrix/classes/src/operations/add.php', | ||
29 | - '5fef6d0e407f3f8887266dfa4a6c534c' => $vendorDir . '/markbaker/matrix/classes/src/operations/directsum.php', | ||
30 | - '684ba247e1385946e3babdaa054119de' => $vendorDir . '/markbaker/matrix/classes/src/operations/subtract.php', | ||
31 | - 'aa53dcba601214d17ad405b7c291b7e8' => $vendorDir . '/markbaker/matrix/classes/src/operations/multiply.php', | ||
32 | - '75c79eb1b25749b05a47976f32b0d8a2' => $vendorDir . '/markbaker/matrix/classes/src/operations/divideby.php', | ||
33 | - '6ab8ad87a734f276a6bcd5a0fe1289be' => $vendorDir . '/markbaker/matrix/classes/src/operations/divideinto.php', | ||
34 | 'abede361264e2ae69ec1eee813a101af' => $vendorDir . '/markbaker/complex/classes/src/functions/abs.php', | 17 | 'abede361264e2ae69ec1eee813a101af' => $vendorDir . '/markbaker/complex/classes/src/functions/abs.php', |
35 | '21a5860fbef5be28db5ddfbc3cca67c4' => $vendorDir . '/markbaker/complex/classes/src/functions/acos.php', | 18 | '21a5860fbef5be28db5ddfbc3cca67c4' => $vendorDir . '/markbaker/complex/classes/src/functions/acos.php', |
36 | '1546e3f9d127f2a9bb2d1b6c31c26ef1' => $vendorDir . '/markbaker/complex/classes/src/functions/acosh.php', | 19 | '1546e3f9d127f2a9bb2d1b6c31c26ef1' => $vendorDir . '/markbaker/complex/classes/src/functions/acosh.php', |
@@ -73,8 +56,23 @@ return array( | @@ -73,8 +56,23 @@ return array( | ||
73 | '883af48563631547925fa4c3b48ead07' => $vendorDir . '/markbaker/complex/classes/src/operations/multiply.php', | 56 | '883af48563631547925fa4c3b48ead07' => $vendorDir . '/markbaker/complex/classes/src/operations/multiply.php', |
74 | 'f190e3308e6ca23234a2875edc985c03' => $vendorDir . '/markbaker/complex/classes/src/operations/divideby.php', | 57 | 'f190e3308e6ca23234a2875edc985c03' => $vendorDir . '/markbaker/complex/classes/src/operations/divideby.php', |
75 | 'ac9e33ce6841aa5bf5d16d465a2f03a7' => $vendorDir . '/markbaker/complex/classes/src/operations/divideinto.php', | 58 | 'ac9e33ce6841aa5bf5d16d465a2f03a7' => $vendorDir . '/markbaker/complex/classes/src/operations/divideinto.php', |
76 | - 'f0e7e63bbb278a92db02393536748c5f' => $vendorDir . '/overtrue/wechat/src/Kernel/Support/Helpers.php', | ||
77 | - '6747f579ad6817f318cc3a7e7a0abb93' => $vendorDir . '/overtrue/wechat/src/Kernel/Helpers.php', | ||
78 | - '1cfd2761b63b0a29ed23657ea394cb2d' => $vendorDir . '/topthink/think-captcha/src/helper.php', | 59 | + '9d8e013a5160a09477beb8e44f8ae97b' => $vendorDir . '/markbaker/matrix/classes/src/functions/adjoint.php', |
60 | + '6e78d1bdea6248d6aa117229efae50f2' => $vendorDir . '/markbaker/matrix/classes/src/functions/antidiagonal.php', | ||
61 | + '4623d87924d94f5412fe5afbf1cef31d' => $vendorDir . '/markbaker/matrix/classes/src/functions/cofactors.php', | ||
62 | + '901fd1f6950a637ca85f66b701a45e13' => $vendorDir . '/markbaker/matrix/classes/src/functions/determinant.php', | ||
63 | + '83057abc0e4acc99ba80154ee5d02a49' => $vendorDir . '/markbaker/matrix/classes/src/functions/diagonal.php', | ||
64 | + '07b7fd7a434451149b4fd477fca0ce06' => $vendorDir . '/markbaker/matrix/classes/src/functions/identity.php', | ||
65 | + 'c8d43b340583e07ae89f2a3baef2cf89' => $vendorDir . '/markbaker/matrix/classes/src/functions/inverse.php', | ||
66 | + '499bb10ed7a3aee2ba4c09a31a85e8d1' => $vendorDir . '/markbaker/matrix/classes/src/functions/minors.php', | ||
67 | + '1cad2e6414d652e8b1c64e8967f6f37d' => $vendorDir . '/markbaker/matrix/classes/src/functions/trace.php', | ||
68 | + '95a7f134ac17161d07def442b3b737e8' => $vendorDir . '/markbaker/matrix/classes/src/functions/transpose.php', | ||
69 | + 'b3a6bc628377118d4b4b8ba08d1eb949' => $vendorDir . '/markbaker/matrix/classes/src/operations/add.php', | ||
70 | + '5fef6d0e407f3f8887266dfa4a6c534c' => $vendorDir . '/markbaker/matrix/classes/src/operations/directsum.php', | ||
71 | + '684ba247e1385946e3babdaa054119de' => $vendorDir . '/markbaker/matrix/classes/src/operations/subtract.php', | ||
72 | + 'aa53dcba601214d17ad405b7c291b7e8' => $vendorDir . '/markbaker/matrix/classes/src/operations/multiply.php', | ||
73 | + '75c79eb1b25749b05a47976f32b0d8a2' => $vendorDir . '/markbaker/matrix/classes/src/operations/divideby.php', | ||
74 | + '6ab8ad87a734f276a6bcd5a0fe1289be' => $vendorDir . '/markbaker/matrix/classes/src/operations/divideinto.php', | ||
79 | '488987c28e9b5e95a1ce6b6bcb94606c' => $vendorDir . '/karsonzhang/fastadmin-addons/src/common.php', | 75 | '488987c28e9b5e95a1ce6b6bcb94606c' => $vendorDir . '/karsonzhang/fastadmin-addons/src/common.php', |
76 | + '9e090711773bfc38738f5dbaee5a7f14' => $vendorDir . '/overtrue/wechat/src/Payment/helpers.php', | ||
77 | + '1cfd2761b63b0a29ed23657ea394cb2d' => $vendorDir . '/topthink/think-captcha/src/helper.php', | ||
80 | ); | 78 | ); |
@@ -7,4 +7,5 @@ $baseDir = dirname($vendorDir); | @@ -7,4 +7,5 @@ $baseDir = dirname($vendorDir); | ||
7 | 7 | ||
8 | return array( | 8 | return array( |
9 | 'Pimple' => array($vendorDir . '/pimple/pimple/src'), | 9 | 'Pimple' => array($vendorDir . '/pimple/pimple/src'), |
10 | + 'Doctrine\\Common\\Cache\\' => array($vendorDir . '/doctrine/cache/lib'), | ||
10 | ); | 11 | ); |
@@ -8,27 +8,19 @@ $baseDir = dirname($vendorDir); | @@ -8,27 +8,19 @@ $baseDir = dirname($vendorDir); | ||
8 | return array( | 8 | return array( |
9 | 'think\\composer\\' => array($vendorDir . '/topthink/think-installer/src'), | 9 | 'think\\composer\\' => array($vendorDir . '/topthink/think-installer/src'), |
10 | 'think\\captcha\\' => array($vendorDir . '/topthink/think-captcha/src'), | 10 | 'think\\captcha\\' => array($vendorDir . '/topthink/think-captcha/src'), |
11 | - 'think\\' => array($baseDir . '/thinkphp/library/think', $vendorDir . '/karsonzhang/fastadmin-addons/src'), | 11 | + 'think\\' => array($vendorDir . '/karsonzhang/fastadmin-addons/src', $baseDir . '/thinkphp/library/think'), |
12 | 'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'), | 12 | 'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'), |
13 | - 'Symfony\\Polyfill\\Php70\\' => array($vendorDir . '/symfony/polyfill-php70'), | ||
14 | 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'), | 13 | 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'), |
15 | 'Symfony\\Polyfill\\Intl\\Normalizer\\' => array($vendorDir . '/symfony/polyfill-intl-normalizer'), | 14 | 'Symfony\\Polyfill\\Intl\\Normalizer\\' => array($vendorDir . '/symfony/polyfill-intl-normalizer'), |
16 | 'Symfony\\Polyfill\\Intl\\Idn\\' => array($vendorDir . '/symfony/polyfill-intl-idn'), | 15 | 'Symfony\\Polyfill\\Intl\\Idn\\' => array($vendorDir . '/symfony/polyfill-intl-idn'), |
17 | - 'Symfony\\Contracts\\Service\\' => array($vendorDir . '/symfony/service-contracts'), | ||
18 | - 'Symfony\\Contracts\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher-contracts'), | ||
19 | - 'Symfony\\Contracts\\Cache\\' => array($vendorDir . '/symfony/cache-contracts'), | ||
20 | 'Symfony\\Component\\VarExporter\\' => array($vendorDir . '/symfony/var-exporter'), | 16 | 'Symfony\\Component\\VarExporter\\' => array($vendorDir . '/symfony/var-exporter'), |
21 | - 'Symfony\\Component\\Mime\\' => array($vendorDir . '/symfony/mime'), | ||
22 | 'Symfony\\Component\\HttpFoundation\\' => array($vendorDir . '/symfony/http-foundation'), | 17 | 'Symfony\\Component\\HttpFoundation\\' => array($vendorDir . '/symfony/http-foundation'), |
23 | 'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'), | 18 | 'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'), |
24 | - 'Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'), | ||
25 | - 'Symfony\\Component\\Cache\\' => array($vendorDir . '/symfony/cache'), | ||
26 | 'Symfony\\Bridge\\PsrHttpMessage\\' => array($vendorDir . '/symfony/psr-http-message-bridge'), | 19 | 'Symfony\\Bridge\\PsrHttpMessage\\' => array($vendorDir . '/symfony/psr-http-message-bridge'), |
27 | 'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'), | 20 | 'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'), |
28 | 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'), | 21 | 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'), |
29 | 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'), | 22 | 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'), |
30 | 'Psr\\Container\\' => array($vendorDir . '/psr/container/src'), | 23 | 'Psr\\Container\\' => array($vendorDir . '/psr/container/src'), |
31 | - 'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'), | ||
32 | 'PhpZip\\' => array($vendorDir . '/nelexa/zip/src'), | 24 | 'PhpZip\\' => array($vendorDir . '/nelexa/zip/src'), |
33 | 'PhpOffice\\PhpSpreadsheet\\' => array($vendorDir . '/phpoffice/phpspreadsheet/src/PhpSpreadsheet'), | 25 | 'PhpOffice\\PhpSpreadsheet\\' => array($vendorDir . '/phpoffice/phpspreadsheet/src/PhpSpreadsheet'), |
34 | 'PHPMailer\\PHPMailer\\' => array($vendorDir . '/phpmailer/phpmailer/src'), | 26 | 'PHPMailer\\PHPMailer\\' => array($vendorDir . '/phpmailer/phpmailer/src'), |
@@ -40,6 +32,5 @@ return array( | @@ -40,6 +32,5 @@ return array( | ||
40 | 'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'), | 32 | 'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'), |
41 | 'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'), | 33 | 'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'), |
42 | 'EasyWeChat\\' => array($vendorDir . '/overtrue/wechat/src'), | 34 | 'EasyWeChat\\' => array($vendorDir . '/overtrue/wechat/src'), |
43 | - 'EasyWeChatComposer\\' => array($vendorDir . '/easywechat-composer/easywechat-composer/src'), | ||
44 | 'Complex\\' => array($vendorDir . '/markbaker/complex/classes/src'), | 35 | 'Complex\\' => array($vendorDir . '/markbaker/complex/classes/src'), |
45 | ); | 36 | ); |
@@ -13,6 +13,9 @@ class ComposerAutoloaderInitf00349b72964a05454b796bb539364c1 | @@ -13,6 +13,9 @@ class ComposerAutoloaderInitf00349b72964a05454b796bb539364c1 | ||
13 | } | 13 | } |
14 | } | 14 | } |
15 | 15 | ||
16 | + /** | ||
17 | + * @return \Composer\Autoload\ClassLoader | ||
18 | + */ | ||
16 | public static function getLoader() | 19 | public static function getLoader() |
17 | { | 20 | { |
18 | if (null !== self::$loader) { | 21 | if (null !== self::$loader) { |
@@ -23,7 +26,7 @@ class ComposerAutoloaderInitf00349b72964a05454b796bb539364c1 | @@ -23,7 +26,7 @@ class ComposerAutoloaderInitf00349b72964a05454b796bb539364c1 | ||
23 | self::$loader = $loader = new \Composer\Autoload\ClassLoader(); | 26 | self::$loader = $loader = new \Composer\Autoload\ClassLoader(); |
24 | spl_autoload_unregister(array('ComposerAutoloaderInitf00349b72964a05454b796bb539364c1', 'loadClassLoader')); | 27 | spl_autoload_unregister(array('ComposerAutoloaderInitf00349b72964a05454b796bb539364c1', 'loadClassLoader')); |
25 | 28 | ||
26 | - $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION'); | 29 | + $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); |
27 | if ($useStaticLoader) { | 30 | if ($useStaticLoader) { |
28 | require_once __DIR__ . '/autoload_static.php'; | 31 | require_once __DIR__ . '/autoload_static.php'; |
29 | 32 |
@@ -7,31 +7,14 @@ namespace Composer\Autoload; | @@ -7,31 +7,14 @@ namespace Composer\Autoload; | ||
7 | class ComposerStaticInitf00349b72964a05454b796bb539364c1 | 7 | class ComposerStaticInitf00349b72964a05454b796bb539364c1 |
8 | { | 8 | { |
9 | public static $files = array ( | 9 | public static $files = array ( |
10 | - '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', | ||
11 | - '25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php', | ||
12 | - '023d27dca8066ef29e6739335ea73bad' => __DIR__ . '/..' . '/symfony/polyfill-php70/bootstrap.php', | ||
13 | - 'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php', | ||
14 | - 'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php', | ||
15 | '7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php', | 10 | '7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php', |
16 | 'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php', | 11 | 'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php', |
12 | + '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', | ||
13 | + 'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php', | ||
14 | + '25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php', | ||
17 | 'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php', | 15 | 'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php', |
16 | + 'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php', | ||
18 | '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php', | 17 | '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php', |
19 | - '9d8e013a5160a09477beb8e44f8ae97b' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/adjoint.php', | ||
20 | - '6e78d1bdea6248d6aa117229efae50f2' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/antidiagonal.php', | ||
21 | - '4623d87924d94f5412fe5afbf1cef31d' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/cofactors.php', | ||
22 | - '901fd1f6950a637ca85f66b701a45e13' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/determinant.php', | ||
23 | - '83057abc0e4acc99ba80154ee5d02a49' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/diagonal.php', | ||
24 | - '07b7fd7a434451149b4fd477fca0ce06' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/identity.php', | ||
25 | - 'c8d43b340583e07ae89f2a3baef2cf89' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/inverse.php', | ||
26 | - '499bb10ed7a3aee2ba4c09a31a85e8d1' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/minors.php', | ||
27 | - '1cad2e6414d652e8b1c64e8967f6f37d' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/trace.php', | ||
28 | - '95a7f134ac17161d07def442b3b737e8' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/transpose.php', | ||
29 | - 'b3a6bc628377118d4b4b8ba08d1eb949' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/add.php', | ||
30 | - '5fef6d0e407f3f8887266dfa4a6c534c' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/directsum.php', | ||
31 | - '684ba247e1385946e3babdaa054119de' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/subtract.php', | ||
32 | - 'aa53dcba601214d17ad405b7c291b7e8' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/multiply.php', | ||
33 | - '75c79eb1b25749b05a47976f32b0d8a2' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/divideby.php', | ||
34 | - '6ab8ad87a734f276a6bcd5a0fe1289be' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/divideinto.php', | ||
35 | 'abede361264e2ae69ec1eee813a101af' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/abs.php', | 18 | 'abede361264e2ae69ec1eee813a101af' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/abs.php', |
36 | '21a5860fbef5be28db5ddfbc3cca67c4' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/acos.php', | 19 | '21a5860fbef5be28db5ddfbc3cca67c4' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/acos.php', |
37 | '1546e3f9d127f2a9bb2d1b6c31c26ef1' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/acosh.php', | 20 | '1546e3f9d127f2a9bb2d1b6c31c26ef1' => __DIR__ . '/..' . '/markbaker/complex/classes/src/functions/acosh.php', |
@@ -74,10 +57,25 @@ class ComposerStaticInitf00349b72964a05454b796bb539364c1 | @@ -74,10 +57,25 @@ class ComposerStaticInitf00349b72964a05454b796bb539364c1 | ||
74 | '883af48563631547925fa4c3b48ead07' => __DIR__ . '/..' . '/markbaker/complex/classes/src/operations/multiply.php', | 57 | '883af48563631547925fa4c3b48ead07' => __DIR__ . '/..' . '/markbaker/complex/classes/src/operations/multiply.php', |
75 | 'f190e3308e6ca23234a2875edc985c03' => __DIR__ . '/..' . '/markbaker/complex/classes/src/operations/divideby.php', | 58 | 'f190e3308e6ca23234a2875edc985c03' => __DIR__ . '/..' . '/markbaker/complex/classes/src/operations/divideby.php', |
76 | 'ac9e33ce6841aa5bf5d16d465a2f03a7' => __DIR__ . '/..' . '/markbaker/complex/classes/src/operations/divideinto.php', | 59 | 'ac9e33ce6841aa5bf5d16d465a2f03a7' => __DIR__ . '/..' . '/markbaker/complex/classes/src/operations/divideinto.php', |
77 | - 'f0e7e63bbb278a92db02393536748c5f' => __DIR__ . '/..' . '/overtrue/wechat/src/Kernel/Support/Helpers.php', | ||
78 | - '6747f579ad6817f318cc3a7e7a0abb93' => __DIR__ . '/..' . '/overtrue/wechat/src/Kernel/Helpers.php', | ||
79 | - '1cfd2761b63b0a29ed23657ea394cb2d' => __DIR__ . '/..' . '/topthink/think-captcha/src/helper.php', | 60 | + '9d8e013a5160a09477beb8e44f8ae97b' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/adjoint.php', |
61 | + '6e78d1bdea6248d6aa117229efae50f2' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/antidiagonal.php', | ||
62 | + '4623d87924d94f5412fe5afbf1cef31d' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/cofactors.php', | ||
63 | + '901fd1f6950a637ca85f66b701a45e13' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/determinant.php', | ||
64 | + '83057abc0e4acc99ba80154ee5d02a49' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/diagonal.php', | ||
65 | + '07b7fd7a434451149b4fd477fca0ce06' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/identity.php', | ||
66 | + 'c8d43b340583e07ae89f2a3baef2cf89' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/inverse.php', | ||
67 | + '499bb10ed7a3aee2ba4c09a31a85e8d1' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/minors.php', | ||
68 | + '1cad2e6414d652e8b1c64e8967f6f37d' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/trace.php', | ||
69 | + '95a7f134ac17161d07def442b3b737e8' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/functions/transpose.php', | ||
70 | + 'b3a6bc628377118d4b4b8ba08d1eb949' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/add.php', | ||
71 | + '5fef6d0e407f3f8887266dfa4a6c534c' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/directsum.php', | ||
72 | + '684ba247e1385946e3babdaa054119de' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/subtract.php', | ||
73 | + 'aa53dcba601214d17ad405b7c291b7e8' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/multiply.php', | ||
74 | + '75c79eb1b25749b05a47976f32b0d8a2' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/divideby.php', | ||
75 | + '6ab8ad87a734f276a6bcd5a0fe1289be' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/operations/divideinto.php', | ||
80 | '488987c28e9b5e95a1ce6b6bcb94606c' => __DIR__ . '/..' . '/karsonzhang/fastadmin-addons/src/common.php', | 76 | '488987c28e9b5e95a1ce6b6bcb94606c' => __DIR__ . '/..' . '/karsonzhang/fastadmin-addons/src/common.php', |
77 | + '9e090711773bfc38738f5dbaee5a7f14' => __DIR__ . '/..' . '/overtrue/wechat/src/Payment/helpers.php', | ||
78 | + '1cfd2761b63b0a29ed23657ea394cb2d' => __DIR__ . '/..' . '/topthink/think-captcha/src/helper.php', | ||
81 | ); | 79 | ); |
82 | 80 | ||
83 | public static $prefixLengthsPsr4 = array ( | 81 | public static $prefixLengthsPsr4 = array ( |
@@ -90,19 +88,12 @@ class ComposerStaticInitf00349b72964a05454b796bb539364c1 | @@ -90,19 +88,12 @@ class ComposerStaticInitf00349b72964a05454b796bb539364c1 | ||
90 | 'S' => | 88 | 'S' => |
91 | array ( | 89 | array ( |
92 | 'Symfony\\Polyfill\\Php72\\' => 23, | 90 | 'Symfony\\Polyfill\\Php72\\' => 23, |
93 | - 'Symfony\\Polyfill\\Php70\\' => 23, | ||
94 | 'Symfony\\Polyfill\\Mbstring\\' => 26, | 91 | 'Symfony\\Polyfill\\Mbstring\\' => 26, |
95 | 'Symfony\\Polyfill\\Intl\\Normalizer\\' => 33, | 92 | 'Symfony\\Polyfill\\Intl\\Normalizer\\' => 33, |
96 | 'Symfony\\Polyfill\\Intl\\Idn\\' => 26, | 93 | 'Symfony\\Polyfill\\Intl\\Idn\\' => 26, |
97 | - 'Symfony\\Contracts\\Service\\' => 26, | ||
98 | - 'Symfony\\Contracts\\EventDispatcher\\' => 34, | ||
99 | - 'Symfony\\Contracts\\Cache\\' => 24, | ||
100 | 'Symfony\\Component\\VarExporter\\' => 30, | 94 | 'Symfony\\Component\\VarExporter\\' => 30, |
101 | - 'Symfony\\Component\\Mime\\' => 23, | ||
102 | 'Symfony\\Component\\HttpFoundation\\' => 33, | 95 | 'Symfony\\Component\\HttpFoundation\\' => 33, |
103 | 'Symfony\\Component\\Finder\\' => 25, | 96 | 'Symfony\\Component\\Finder\\' => 25, |
104 | - 'Symfony\\Component\\EventDispatcher\\' => 34, | ||
105 | - 'Symfony\\Component\\Cache\\' => 24, | ||
106 | 'Symfony\\Bridge\\PsrHttpMessage\\' => 30, | 97 | 'Symfony\\Bridge\\PsrHttpMessage\\' => 30, |
107 | ), | 98 | ), |
108 | 'P' => | 99 | 'P' => |
@@ -111,7 +102,6 @@ class ComposerStaticInitf00349b72964a05454b796bb539364c1 | @@ -111,7 +102,6 @@ class ComposerStaticInitf00349b72964a05454b796bb539364c1 | ||
111 | 'Psr\\Log\\' => 8, | 102 | 'Psr\\Log\\' => 8, |
112 | 'Psr\\Http\\Message\\' => 17, | 103 | 'Psr\\Http\\Message\\' => 17, |
113 | 'Psr\\Container\\' => 14, | 104 | 'Psr\\Container\\' => 14, |
114 | - 'Psr\\Cache\\' => 10, | ||
115 | 'PhpZip\\' => 7, | 105 | 'PhpZip\\' => 7, |
116 | 'PhpOffice\\PhpSpreadsheet\\' => 25, | 106 | 'PhpOffice\\PhpSpreadsheet\\' => 25, |
117 | 'PHPMailer\\PHPMailer\\' => 20, | 107 | 'PHPMailer\\PHPMailer\\' => 20, |
@@ -135,7 +125,6 @@ class ComposerStaticInitf00349b72964a05454b796bb539364c1 | @@ -135,7 +125,6 @@ class ComposerStaticInitf00349b72964a05454b796bb539364c1 | ||
135 | 'E' => | 125 | 'E' => |
136 | array ( | 126 | array ( |
137 | 'EasyWeChat\\' => 11, | 127 | 'EasyWeChat\\' => 11, |
138 | - 'EasyWeChatComposer\\' => 19, | ||
139 | ), | 128 | ), |
140 | 'C' => | 129 | 'C' => |
141 | array ( | 130 | array ( |
@@ -154,17 +143,13 @@ class ComposerStaticInitf00349b72964a05454b796bb539364c1 | @@ -154,17 +143,13 @@ class ComposerStaticInitf00349b72964a05454b796bb539364c1 | ||
154 | ), | 143 | ), |
155 | 'think\\' => | 144 | 'think\\' => |
156 | array ( | 145 | array ( |
157 | - 0 => __DIR__ . '/../..' . '/thinkphp/library/think', | ||
158 | - 1 => __DIR__ . '/..' . '/karsonzhang/fastadmin-addons/src', | 146 | + 0 => __DIR__ . '/..' . '/karsonzhang/fastadmin-addons/src', |
147 | + 1 => __DIR__ . '/../..' . '/thinkphp/library/think', | ||
159 | ), | 148 | ), |
160 | 'Symfony\\Polyfill\\Php72\\' => | 149 | 'Symfony\\Polyfill\\Php72\\' => |
161 | array ( | 150 | array ( |
162 | 0 => __DIR__ . '/..' . '/symfony/polyfill-php72', | 151 | 0 => __DIR__ . '/..' . '/symfony/polyfill-php72', |
163 | ), | 152 | ), |
164 | - 'Symfony\\Polyfill\\Php70\\' => | ||
165 | - array ( | ||
166 | - 0 => __DIR__ . '/..' . '/symfony/polyfill-php70', | ||
167 | - ), | ||
168 | 'Symfony\\Polyfill\\Mbstring\\' => | 153 | 'Symfony\\Polyfill\\Mbstring\\' => |
169 | array ( | 154 | array ( |
170 | 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring', | 155 | 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring', |
@@ -177,26 +162,10 @@ class ComposerStaticInitf00349b72964a05454b796bb539364c1 | @@ -177,26 +162,10 @@ class ComposerStaticInitf00349b72964a05454b796bb539364c1 | ||
177 | array ( | 162 | array ( |
178 | 0 => __DIR__ . '/..' . '/symfony/polyfill-intl-idn', | 163 | 0 => __DIR__ . '/..' . '/symfony/polyfill-intl-idn', |
179 | ), | 164 | ), |
180 | - 'Symfony\\Contracts\\Service\\' => | ||
181 | - array ( | ||
182 | - 0 => __DIR__ . '/..' . '/symfony/service-contracts', | ||
183 | - ), | ||
184 | - 'Symfony\\Contracts\\EventDispatcher\\' => | ||
185 | - array ( | ||
186 | - 0 => __DIR__ . '/..' . '/symfony/event-dispatcher-contracts', | ||
187 | - ), | ||
188 | - 'Symfony\\Contracts\\Cache\\' => | ||
189 | - array ( | ||
190 | - 0 => __DIR__ . '/..' . '/symfony/cache-contracts', | ||
191 | - ), | ||
192 | 'Symfony\\Component\\VarExporter\\' => | 165 | 'Symfony\\Component\\VarExporter\\' => |
193 | array ( | 166 | array ( |
194 | 0 => __DIR__ . '/..' . '/symfony/var-exporter', | 167 | 0 => __DIR__ . '/..' . '/symfony/var-exporter', |
195 | ), | 168 | ), |
196 | - 'Symfony\\Component\\Mime\\' => | ||
197 | - array ( | ||
198 | - 0 => __DIR__ . '/..' . '/symfony/mime', | ||
199 | - ), | ||
200 | 'Symfony\\Component\\HttpFoundation\\' => | 169 | 'Symfony\\Component\\HttpFoundation\\' => |
201 | array ( | 170 | array ( |
202 | 0 => __DIR__ . '/..' . '/symfony/http-foundation', | 171 | 0 => __DIR__ . '/..' . '/symfony/http-foundation', |
@@ -205,14 +174,6 @@ class ComposerStaticInitf00349b72964a05454b796bb539364c1 | @@ -205,14 +174,6 @@ class ComposerStaticInitf00349b72964a05454b796bb539364c1 | ||
205 | array ( | 174 | array ( |
206 | 0 => __DIR__ . '/..' . '/symfony/finder', | 175 | 0 => __DIR__ . '/..' . '/symfony/finder', |
207 | ), | 176 | ), |
208 | - 'Symfony\\Component\\EventDispatcher\\' => | ||
209 | - array ( | ||
210 | - 0 => __DIR__ . '/..' . '/symfony/event-dispatcher', | ||
211 | - ), | ||
212 | - 'Symfony\\Component\\Cache\\' => | ||
213 | - array ( | ||
214 | - 0 => __DIR__ . '/..' . '/symfony/cache', | ||
215 | - ), | ||
216 | 'Symfony\\Bridge\\PsrHttpMessage\\' => | 177 | 'Symfony\\Bridge\\PsrHttpMessage\\' => |
217 | array ( | 178 | array ( |
218 | 0 => __DIR__ . '/..' . '/symfony/psr-http-message-bridge', | 179 | 0 => __DIR__ . '/..' . '/symfony/psr-http-message-bridge', |
@@ -233,10 +194,6 @@ class ComposerStaticInitf00349b72964a05454b796bb539364c1 | @@ -233,10 +194,6 @@ class ComposerStaticInitf00349b72964a05454b796bb539364c1 | ||
233 | array ( | 194 | array ( |
234 | 0 => __DIR__ . '/..' . '/psr/container/src', | 195 | 0 => __DIR__ . '/..' . '/psr/container/src', |
235 | ), | 196 | ), |
236 | - 'Psr\\Cache\\' => | ||
237 | - array ( | ||
238 | - 0 => __DIR__ . '/..' . '/psr/cache/src', | ||
239 | - ), | ||
240 | 'PhpZip\\' => | 197 | 'PhpZip\\' => |
241 | array ( | 198 | array ( |
242 | 0 => __DIR__ . '/..' . '/nelexa/zip/src', | 199 | 0 => __DIR__ . '/..' . '/nelexa/zip/src', |
@@ -281,10 +238,6 @@ class ComposerStaticInitf00349b72964a05454b796bb539364c1 | @@ -281,10 +238,6 @@ class ComposerStaticInitf00349b72964a05454b796bb539364c1 | ||
281 | array ( | 238 | array ( |
282 | 0 => __DIR__ . '/..' . '/overtrue/wechat/src', | 239 | 0 => __DIR__ . '/..' . '/overtrue/wechat/src', |
283 | ), | 240 | ), |
284 | - 'EasyWeChatComposer\\' => | ||
285 | - array ( | ||
286 | - 0 => __DIR__ . '/..' . '/easywechat-composer/easywechat-composer/src', | ||
287 | - ), | ||
288 | 'Complex\\' => | 241 | 'Complex\\' => |
289 | array ( | 242 | array ( |
290 | 0 => __DIR__ . '/..' . '/markbaker/complex/classes/src', | 243 | 0 => __DIR__ . '/..' . '/markbaker/complex/classes/src', |
@@ -299,17 +252,17 @@ class ComposerStaticInitf00349b72964a05454b796bb539364c1 | @@ -299,17 +252,17 @@ class ComposerStaticInitf00349b72964a05454b796bb539364c1 | ||
299 | 0 => __DIR__ . '/..' . '/pimple/pimple/src', | 252 | 0 => __DIR__ . '/..' . '/pimple/pimple/src', |
300 | ), | 253 | ), |
301 | ), | 254 | ), |
255 | + 'D' => | ||
256 | + array ( | ||
257 | + 'Doctrine\\Common\\Cache\\' => | ||
258 | + array ( | ||
259 | + 0 => __DIR__ . '/..' . '/doctrine/cache/lib', | ||
260 | + ), | ||
261 | + ), | ||
302 | ); | 262 | ); |
303 | 263 | ||
304 | public static $classMap = array ( | 264 | public static $classMap = array ( |
305 | - 'ArithmeticError' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/ArithmeticError.php', | ||
306 | - 'AssertionError' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/AssertionError.php', | ||
307 | - 'DivisionByZeroError' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/DivisionByZeroError.php', | ||
308 | - 'Error' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/Error.php', | ||
309 | 'Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php', | 265 | 'Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php', |
310 | - 'ParseError' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/ParseError.php', | ||
311 | - 'SessionUpdateTimestampHandlerInterface' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/SessionUpdateTimestampHandlerInterface.php', | ||
312 | - 'TypeError' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/TypeError.php', | ||
313 | ); | 266 | ); |
314 | 267 | ||
315 | public static function getInitializer(ClassLoader $loader) | 268 | public static function getInitializer(ClassLoader $loader) |
此 diff 太大无法显示。
vendor/doctrine/cache/.coveralls.yml
0 → 100644
vendor/doctrine/cache/.gitignore
0 → 100644
vendor/doctrine/cache/.travis.yml
0 → 100644
1 | +language: php | ||
2 | + | ||
3 | +php: | ||
4 | + - 5.3 | ||
5 | + - 5.4 | ||
6 | + - 5.5 | ||
7 | + - 5.6 | ||
8 | + - hhvm | ||
9 | + | ||
10 | +services: | ||
11 | + - riak | ||
12 | + - mongodb | ||
13 | + - memcached | ||
14 | + - redis-server | ||
15 | + | ||
16 | +before_install: | ||
17 | + - sh -c "if [ $TRAVIS_PHP_VERSION != 'hhvm' ]; then pecl install riak-beta; fi" | ||
18 | + - sh -c "if [[ $TRAVIS_PHP_VERSION != 'hhvm' && `php-config --vernum` -ge 50500 ]] ; then pecl config-set preferred_state beta; printf "yes\n" | pecl install apcu ; else echo 'extension="apc.so"' >> ./tests/travis/php.ini ;fi" | ||
19 | + - composer self-update | ||
20 | + - sh -c "if [ $TRAVIS_PHP_VERSION != 'hhvm' ]; then phpenv config-add ./tests/travis/php.ini; fi" | ||
21 | + | ||
22 | +install: | ||
23 | + - composer --prefer-source --dev install | ||
24 | + | ||
25 | +script: | ||
26 | + - ./vendor/bin/phpunit -c ./tests/travis/phpunit.travis.xml -v | ||
27 | + | ||
28 | +after_script: | ||
29 | + - php vendor/bin/coveralls -v | ||
30 | + | ||
31 | +matrix: | ||
32 | + allow_failures: | ||
33 | + - php: hhvm |
vendor/doctrine/cache/LICENSE
0 → 100644
1 | +Copyright (c) 2006-2012 Doctrine Project | ||
2 | + | ||
3 | +Permission is hereby granted, free of charge, to any person obtaining a copy of | ||
4 | +this software and associated documentation files (the "Software"), to deal in | ||
5 | +the Software without restriction, including without limitation the rights to | ||
6 | +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | ||
7 | +of the Software, and to permit persons to whom the Software is furnished to do | ||
8 | +so, subject to the following conditions: | ||
9 | + | ||
10 | +The above copyright notice and this permission notice shall be included in all | ||
11 | +copies or substantial portions of the Software. | ||
12 | + | ||
13 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
14 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
15 | +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
16 | +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
17 | +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
18 | +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
19 | +SOFTWARE. |
vendor/doctrine/cache/README.md
0 → 100644
1 | +# Doctrine Cache | ||
2 | + | ||
3 | +Master: [![Build Status](https://secure.travis-ci.org/doctrine/cache.png?branch=master)](http://travis-ci.org/doctrine/cache) [![Coverage Status](https://coveralls.io/repos/doctrine/cache/badge.png?branch=master)](https://coveralls.io/r/doctrine/cache?branch=master) | ||
4 | + | ||
5 | +[![Latest Stable Version](https://poser.pugx.org/doctrine/cache/v/stable.png)](https://packagist.org/packages/doctrine/cache) [![Total Downloads](https://poser.pugx.org/doctrine/cache/downloads.png)](https://packagist.org/packages/doctrine/cache) | ||
6 | + | ||
7 | +Cache component extracted from the Doctrine Common project. | ||
8 | + | ||
9 | +## Changelog | ||
10 | + | ||
11 | +### v1.2 | ||
12 | + | ||
13 | +* Added support for MongoDB as Cache Provider | ||
14 | +* Fix namespace version reset |
vendor/doctrine/cache/UPGRADE.md
0 → 100644
1 | +# Upgrade to 1.4 | ||
2 | + | ||
3 | +## Minor BC Break: `Doctrine\Common\Cache\FileCache#$extension` is now `private`. | ||
4 | + | ||
5 | +If you need to override the value of `Doctrine\Common\Cache\FileCache#$extension`, then use the | ||
6 | +second parameter of `Doctrine\Common\Cache\FileCache#__construct()` instead of overriding | ||
7 | +the property in your own implementation. | ||
8 | + | ||
9 | +## Minor BC Break: file based caches paths changed | ||
10 | + | ||
11 | +`Doctrine\Common\Cache\FileCache`, `Doctrine\Common\Cache\PhpFileCache` and | ||
12 | +`Doctrine\Common\Cache\FilesystemCache` are using a different cache paths structure. | ||
13 | + | ||
14 | +If you rely on warmed up caches for deployments, consider that caches generated | ||
15 | +with `doctrine/cache` `<1.4` are not compatible with the new directory structure, | ||
16 | +and will be ignored. |
vendor/doctrine/cache/build.properties
0 → 100644
vendor/doctrine/cache/build.xml
0 → 100644
1 | +<?xml version="1.0"?> | ||
2 | +<project name="DoctrineCommonCache" default="build" basedir="."> | ||
3 | + <property file="build.properties" /> | ||
4 | + | ||
5 | + <target name="php"> | ||
6 | + <exec executable="which" outputproperty="php_executable"> | ||
7 | + <arg value="php" /> | ||
8 | + </exec> | ||
9 | + </target> | ||
10 | + | ||
11 | + <target name="prepare"> | ||
12 | + <mkdir dir="build" /> | ||
13 | + </target> | ||
14 | + | ||
15 | + <target name="build" depends="check-git-checkout-clean,prepare,php,composer"> | ||
16 | + <exec executable="${php_executable}"> | ||
17 | + <arg value="build/composer.phar" /> | ||
18 | + <arg value="archive" /> | ||
19 | + <arg value="--dir=build" /> | ||
20 | + </exec> | ||
21 | + </target> | ||
22 | + | ||
23 | + <target name="composer" depends="php,composer-check,composer-download"> | ||
24 | + <exec executable="${php_executable}"> | ||
25 | + <arg value="build/composer.phar" /> | ||
26 | + <arg value="install" /> | ||
27 | + </exec> | ||
28 | + </target> | ||
29 | + | ||
30 | + <target name="composer-check" depends="prepare"> | ||
31 | + <available file="build/composer.phar" property="composer.present"/> | ||
32 | + </target> | ||
33 | + | ||
34 | + <target name="composer-download" unless="composer.present"> | ||
35 | + <exec executable="wget"> | ||
36 | + <arg value="-Obuild/composer.phar" /> | ||
37 | + <arg value="http://getcomposer.org/composer.phar" /> | ||
38 | + </exec> | ||
39 | + </target> | ||
40 | + | ||
41 | + <target name="make-release" depends="check-git-checkout-clean,prepare,php"> | ||
42 | + <replace file="${project.version_file}" token="-DEV" value="" failOnNoReplacements="true" /> | ||
43 | + <exec executable="git" failonerror="true" outputproperty="current_git_branch"> | ||
44 | + <arg value="rev-parse" /> | ||
45 | + <arg value="--abbrev-ref" /> | ||
46 | + <arg value="HEAD" /> | ||
47 | + </exec> | ||
48 | + <exec executable="${php_executable}" outputproperty="doctrine.current_version" failonerror="true"> | ||
49 | + <arg value="-r" /> | ||
50 | + <arg value="require_once '${project.version_file}';echo ${project.version_class}::VERSION;" /> | ||
51 | + </exec> | ||
52 | + <exec executable="${php_executable}" outputproperty="doctrine.next_version" failonerror="true"> | ||
53 | + <arg value="-r" /> | ||
54 | + <arg value="$parts = explode('.', str_ireplace(array('-DEV', '-ALPHA', '-BETA'), '', '${doctrine.current_version}')); | ||
55 | + if (count($parts) != 3) { | ||
56 | + throw new \InvalidArgumentException('Version is assumed in format x.y.z, ${doctrine.current_version} given'); | ||
57 | + } | ||
58 | + if ('${current_git_branch}' === 'master') { | ||
59 | + $parts[1]++; | ||
60 | + } else { | ||
61 | + $parts[2]++; | ||
62 | + } | ||
63 | + echo implode('.', $parts); | ||
64 | + " /> | ||
65 | + </exec> | ||
66 | + | ||
67 | + <git-commit file="${project.version_file}" message="Release ${doctrine.current_version}" /> | ||
68 | + <git-tag version="${doctrine.current_version}" /> | ||
69 | + <replace file="${project.version_file}" token="${doctrine.current_version}" value="${doctrine.next_version}-DEV" /> | ||
70 | + <git-commit file="${project.version_file}" message="Bump version to ${doctrine.next_version}" /> | ||
71 | + </target> | ||
72 | + | ||
73 | + <target name="check-git-checkout-clean"> | ||
74 | + <exec executable="git" failonerror="true"> | ||
75 | + <arg value="diff-index" /> | ||
76 | + <arg value="--quiet" /> | ||
77 | + <arg value="HEAD" /> | ||
78 | + </exec> | ||
79 | + </target> | ||
80 | + | ||
81 | + <macrodef name="git-commit"> | ||
82 | + <attribute name="file" default="NOT SET"/> | ||
83 | + <attribute name="message" default="NOT SET"/> | ||
84 | + | ||
85 | + <sequential> | ||
86 | + <exec executable="git"> | ||
87 | + <arg value="add" /> | ||
88 | + <arg value="@{file}" /> | ||
89 | + </exec> | ||
90 | + <exec executable="git"> | ||
91 | + <arg value="commit" /> | ||
92 | + <arg value="-m" /> | ||
93 | + <arg value="@{message}" /> | ||
94 | + </exec> | ||
95 | + </sequential> | ||
96 | + </macrodef> | ||
97 | + | ||
98 | + <macrodef name="git-tag"> | ||
99 | + <attribute name="version" default="NOT SET" /> | ||
100 | + | ||
101 | + <sequential> | ||
102 | + <exec executable="git"> | ||
103 | + <arg value="tag" /> | ||
104 | + <arg value="-m" /> | ||
105 | + <arg value="v@{version}" /> | ||
106 | + <arg value="v@{version}" /> | ||
107 | + </exec> | ||
108 | + </sequential> | ||
109 | + </macrodef> | ||
110 | +</project> |
vendor/doctrine/cache/composer.json
0 → 100644
1 | +{ | ||
2 | + "name": "doctrine/cache", | ||
3 | + "type": "library", | ||
4 | + "description": "Caching library offering an object-oriented API for many cache backends", | ||
5 | + "keywords": ["cache", "caching"], | ||
6 | + "homepage": "http://www.doctrine-project.org", | ||
7 | + "license": "MIT", | ||
8 | + "authors": [ | ||
9 | + {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"}, | ||
10 | + {"name": "Roman Borschel", "email": "roman@code-factory.org"}, | ||
11 | + {"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"}, | ||
12 | + {"name": "Jonathan Wage", "email": "jonwage@gmail.com"}, | ||
13 | + {"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"} | ||
14 | + ], | ||
15 | + "require": { | ||
16 | + "php": ">=5.3.2" | ||
17 | + }, | ||
18 | + "require-dev": { | ||
19 | + "phpunit/phpunit": ">=3.7", | ||
20 | + "satooshi/php-coveralls": "~0.6", | ||
21 | + "predis/predis": "~1.0" | ||
22 | + }, | ||
23 | + "conflict": { | ||
24 | + "doctrine/common": ">2.2,<2.4" | ||
25 | + }, | ||
26 | + "autoload": { | ||
27 | + "psr-0": { "Doctrine\\Common\\Cache\\": "lib/" } | ||
28 | + }, | ||
29 | + "extra": { | ||
30 | + "branch-alias": { | ||
31 | + "dev-master": "1.5.x-dev" | ||
32 | + } | ||
33 | + } | ||
34 | +} |
1 | +<?php | ||
2 | +/* | ||
3 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4 | + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
5 | + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
6 | + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
7 | + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
8 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
9 | + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
10 | + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
11 | + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
12 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
13 | + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
14 | + * | ||
15 | + * This software consists of voluntary contributions made by many individuals | ||
16 | + * and is licensed under the MIT license. For more information, see | ||
17 | + * <http://www.doctrine-project.org>. | ||
18 | + */ | ||
19 | + | ||
20 | +namespace Doctrine\Common\Cache; | ||
21 | + | ||
22 | +/** | ||
23 | + * APC cache provider. | ||
24 | + * | ||
25 | + * @link www.doctrine-project.org | ||
26 | + * @since 2.0 | ||
27 | + * @author Benjamin Eberlei <kontakt@beberlei.de> | ||
28 | + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> | ||
29 | + * @author Jonathan Wage <jonwage@gmail.com> | ||
30 | + * @author Roman Borschel <roman@code-factory.org> | ||
31 | + * @author David Abdemoulaie <dave@hobodave.com> | ||
32 | + */ | ||
33 | +class ApcCache extends CacheProvider | ||
34 | +{ | ||
35 | + /** | ||
36 | + * {@inheritdoc} | ||
37 | + */ | ||
38 | + protected function doFetch($id) | ||
39 | + { | ||
40 | + return apc_fetch($id); | ||
41 | + } | ||
42 | + | ||
43 | + /** | ||
44 | + * {@inheritdoc} | ||
45 | + */ | ||
46 | + protected function doContains($id) | ||
47 | + { | ||
48 | + return apc_exists($id); | ||
49 | + } | ||
50 | + | ||
51 | + /** | ||
52 | + * {@inheritdoc} | ||
53 | + */ | ||
54 | + protected function doSave($id, $data, $lifeTime = 0) | ||
55 | + { | ||
56 | + return (bool) apc_store($id, $data, (int) $lifeTime); | ||
57 | + } | ||
58 | + | ||
59 | + /** | ||
60 | + * {@inheritdoc} | ||
61 | + */ | ||
62 | + protected function doDelete($id) | ||
63 | + { | ||
64 | + // apc_delete returns false if the id does not exist | ||
65 | + return apc_delete($id) || ! apc_exists($id); | ||
66 | + } | ||
67 | + | ||
68 | + /** | ||
69 | + * {@inheritdoc} | ||
70 | + */ | ||
71 | + protected function doFlush() | ||
72 | + { | ||
73 | + return apc_clear_cache() && apc_clear_cache('user'); | ||
74 | + } | ||
75 | + | ||
76 | + /** | ||
77 | + * {@inheritdoc} | ||
78 | + */ | ||
79 | + protected function doFetchMultiple(array $keys) | ||
80 | + { | ||
81 | + return apc_fetch($keys); | ||
82 | + } | ||
83 | + | ||
84 | + /** | ||
85 | + * {@inheritdoc} | ||
86 | + */ | ||
87 | + protected function doGetStats() | ||
88 | + { | ||
89 | + $info = apc_cache_info('', true); | ||
90 | + $sma = apc_sma_info(); | ||
91 | + | ||
92 | + // @TODO - Temporary fix @see https://github.com/krakjoe/apcu/pull/42 | ||
93 | + if (PHP_VERSION_ID >= 50500) { | ||
94 | + $info['num_hits'] = isset($info['num_hits']) ? $info['num_hits'] : $info['nhits']; | ||
95 | + $info['num_misses'] = isset($info['num_misses']) ? $info['num_misses'] : $info['nmisses']; | ||
96 | + $info['start_time'] = isset($info['start_time']) ? $info['start_time'] : $info['stime']; | ||
97 | + } | ||
98 | + | ||
99 | + return array( | ||
100 | + Cache::STATS_HITS => $info['num_hits'], | ||
101 | + Cache::STATS_MISSES => $info['num_misses'], | ||
102 | + Cache::STATS_UPTIME => $info['start_time'], | ||
103 | + Cache::STATS_MEMORY_USAGE => $info['mem_size'], | ||
104 | + Cache::STATS_MEMORY_AVAILABLE => $sma['avail_mem'], | ||
105 | + ); | ||
106 | + } | ||
107 | +} |
1 | +<?php | ||
2 | +/* | ||
3 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4 | + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
5 | + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
6 | + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
7 | + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
8 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
9 | + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
10 | + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
11 | + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
12 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
13 | + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
14 | + * | ||
15 | + * This software consists of voluntary contributions made by many individuals | ||
16 | + * and is licensed under the MIT license. For more information, see | ||
17 | + * <http://www.doctrine-project.org>. | ||
18 | + */ | ||
19 | + | ||
20 | +namespace Doctrine\Common\Cache; | ||
21 | + | ||
22 | +/** | ||
23 | + * Array cache driver. | ||
24 | + * | ||
25 | + * @link www.doctrine-project.org | ||
26 | + * @since 2.0 | ||
27 | + * @author Benjamin Eberlei <kontakt@beberlei.de> | ||
28 | + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> | ||
29 | + * @author Jonathan Wage <jonwage@gmail.com> | ||
30 | + * @author Roman Borschel <roman@code-factory.org> | ||
31 | + * @author David Abdemoulaie <dave@hobodave.com> | ||
32 | + */ | ||
33 | +class ArrayCache extends CacheProvider | ||
34 | +{ | ||
35 | + /** | ||
36 | + * @var array $data | ||
37 | + */ | ||
38 | + private $data = array(); | ||
39 | + | ||
40 | + /** | ||
41 | + * {@inheritdoc} | ||
42 | + */ | ||
43 | + protected function doFetch($id) | ||
44 | + { | ||
45 | + return $this->doContains($id) ? $this->data[$id] : false; | ||
46 | + } | ||
47 | + | ||
48 | + /** | ||
49 | + * {@inheritdoc} | ||
50 | + */ | ||
51 | + protected function doContains($id) | ||
52 | + { | ||
53 | + // isset() is required for performance optimizations, to avoid unnecessary function calls to array_key_exists. | ||
54 | + return isset($this->data[$id]) || array_key_exists($id, $this->data); | ||
55 | + } | ||
56 | + | ||
57 | + /** | ||
58 | + * {@inheritdoc} | ||
59 | + */ | ||
60 | + protected function doSave($id, $data, $lifeTime = 0) | ||
61 | + { | ||
62 | + $this->data[$id] = $data; | ||
63 | + | ||
64 | + return true; | ||
65 | + } | ||
66 | + | ||
67 | + /** | ||
68 | + * {@inheritdoc} | ||
69 | + */ | ||
70 | + protected function doDelete($id) | ||
71 | + { | ||
72 | + unset($this->data[$id]); | ||
73 | + | ||
74 | + return true; | ||
75 | + } | ||
76 | + | ||
77 | + /** | ||
78 | + * {@inheritdoc} | ||
79 | + */ | ||
80 | + protected function doFlush() | ||
81 | + { | ||
82 | + $this->data = array(); | ||
83 | + | ||
84 | + return true; | ||
85 | + } | ||
86 | + | ||
87 | + /** | ||
88 | + * {@inheritdoc} | ||
89 | + */ | ||
90 | + protected function doGetStats() | ||
91 | + { | ||
92 | + return null; | ||
93 | + } | ||
94 | +} |
1 | +<?php | ||
2 | +/* | ||
3 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4 | + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
5 | + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
6 | + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
7 | + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
8 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
9 | + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
10 | + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
11 | + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
12 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
13 | + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
14 | + * | ||
15 | + * This software consists of voluntary contributions made by many individuals | ||
16 | + * and is licensed under the MIT license. For more information, see | ||
17 | + * <http://www.doctrine-project.org>. | ||
18 | + */ | ||
19 | + | ||
20 | +namespace Doctrine\Common\Cache; | ||
21 | + | ||
22 | +/** | ||
23 | + * Interface for cache drivers. | ||
24 | + * | ||
25 | + * @link www.doctrine-project.org | ||
26 | + * @since 2.0 | ||
27 | + * @author Benjamin Eberlei <kontakt@beberlei.de> | ||
28 | + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> | ||
29 | + * @author Jonathan Wage <jonwage@gmail.com> | ||
30 | + * @author Roman Borschel <roman@code-factory.org> | ||
31 | + * @author Fabio B. Silva <fabio.bat.silva@gmail.com> | ||
32 | + * @author Kévin Dunglas <dunglas@gmail.com> | ||
33 | + */ | ||
34 | +interface Cache | ||
35 | +{ | ||
36 | + const STATS_HITS = 'hits'; | ||
37 | + const STATS_MISSES = 'misses'; | ||
38 | + const STATS_UPTIME = 'uptime'; | ||
39 | + const STATS_MEMORY_USAGE = 'memory_usage'; | ||
40 | + const STATS_MEMORY_AVAILABLE = 'memory_available'; | ||
41 | + /** | ||
42 | + * Only for backward compatibility (may be removed in next major release) | ||
43 | + * | ||
44 | + * @deprecated | ||
45 | + */ | ||
46 | + const STATS_MEMORY_AVAILIABLE = 'memory_available'; | ||
47 | + | ||
48 | + /** | ||
49 | + * Fetches an entry from the cache. | ||
50 | + * | ||
51 | + * @param string $id The id of the cache entry to fetch. | ||
52 | + * | ||
53 | + * @return mixed The cached data or FALSE, if no cache entry exists for the given id. | ||
54 | + */ | ||
55 | + public function fetch($id); | ||
56 | + | ||
57 | + /** | ||
58 | + * Tests if an entry exists in the cache. | ||
59 | + * | ||
60 | + * @param string $id The cache id of the entry to check for. | ||
61 | + * | ||
62 | + * @return boolean TRUE if a cache entry exists for the given cache id, FALSE otherwise. | ||
63 | + */ | ||
64 | + public function contains($id); | ||
65 | + | ||
66 | + /** | ||
67 | + * Puts data into the cache. | ||
68 | + * | ||
69 | + * If a cache entry with the given id already exists, its data will be replaced. | ||
70 | + * | ||
71 | + * @param string $id The cache id. | ||
72 | + * @param mixed $data The cache entry/data. | ||
73 | + * @param int $lifeTime The lifetime in number of seconds for this cache entry. | ||
74 | + * If zero (the default), the entry never expires (although it may be deleted from the cache | ||
75 | + * to make place for other entries). | ||
76 | + * | ||
77 | + * @return boolean TRUE if the entry was successfully stored in the cache, FALSE otherwise. | ||
78 | + */ | ||
79 | + public function save($id, $data, $lifeTime = 0); | ||
80 | + | ||
81 | + /** | ||
82 | + * Deletes a cache entry. | ||
83 | + * | ||
84 | + * @param string $id The cache id. | ||
85 | + * | ||
86 | + * @return boolean TRUE if the cache entry was successfully deleted, FALSE otherwise. | ||
87 | + * Deleting a non-existing entry is considered successful. | ||
88 | + */ | ||
89 | + public function delete($id); | ||
90 | + | ||
91 | + /** | ||
92 | + * Retrieves cached information from the data store. | ||
93 | + * | ||
94 | + * The server's statistics array has the following values: | ||
95 | + * | ||
96 | + * - <b>hits</b> | ||
97 | + * Number of keys that have been requested and found present. | ||
98 | + * | ||
99 | + * - <b>misses</b> | ||
100 | + * Number of items that have been requested and not found. | ||
101 | + * | ||
102 | + * - <b>uptime</b> | ||
103 | + * Time that the server is running. | ||
104 | + * | ||
105 | + * - <b>memory_usage</b> | ||
106 | + * Memory used by this server to store items. | ||
107 | + * | ||
108 | + * - <b>memory_available</b> | ||
109 | + * Memory allowed to use for storage. | ||
110 | + * | ||
111 | + * @since 2.2 | ||
112 | + * | ||
113 | + * @return array|null An associative array with server's statistics if available, NULL otherwise. | ||
114 | + */ | ||
115 | + public function getStats(); | ||
116 | +} |
1 | +<?php | ||
2 | +/* | ||
3 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4 | + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
5 | + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
6 | + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
7 | + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
8 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
9 | + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
10 | + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
11 | + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
12 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
13 | + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
14 | + * | ||
15 | + * This software consists of voluntary contributions made by many individuals | ||
16 | + * and is licensed under the MIT license. For more information, see | ||
17 | + * <http://www.doctrine-project.org>. | ||
18 | + */ | ||
19 | + | ||
20 | +namespace Doctrine\Common\Cache; | ||
21 | + | ||
22 | +/** | ||
23 | + * Base class for cache provider implementations. | ||
24 | + * | ||
25 | + * @since 2.2 | ||
26 | + * @author Benjamin Eberlei <kontakt@beberlei.de> | ||
27 | + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> | ||
28 | + * @author Jonathan Wage <jonwage@gmail.com> | ||
29 | + * @author Roman Borschel <roman@code-factory.org> | ||
30 | + * @author Fabio B. Silva <fabio.bat.silva@gmail.com> | ||
31 | + */ | ||
32 | +abstract class CacheProvider implements Cache, FlushableCache, ClearableCache, MultiGetCache | ||
33 | +{ | ||
34 | + const DOCTRINE_NAMESPACE_CACHEKEY = 'DoctrineNamespaceCacheKey[%s]'; | ||
35 | + | ||
36 | + /** | ||
37 | + * The namespace to prefix all cache ids with. | ||
38 | + * | ||
39 | + * @var string | ||
40 | + */ | ||
41 | + private $namespace = ''; | ||
42 | + | ||
43 | + /** | ||
44 | + * The namespace version. | ||
45 | + * | ||
46 | + * @var integer|null | ||
47 | + */ | ||
48 | + private $namespaceVersion; | ||
49 | + | ||
50 | + /** | ||
51 | + * Sets the namespace to prefix all cache ids with. | ||
52 | + * | ||
53 | + * @param string $namespace | ||
54 | + * | ||
55 | + * @return void | ||
56 | + */ | ||
57 | + public function setNamespace($namespace) | ||
58 | + { | ||
59 | + $this->namespace = (string) $namespace; | ||
60 | + $this->namespaceVersion = null; | ||
61 | + } | ||
62 | + | ||
63 | + /** | ||
64 | + * Retrieves the namespace that prefixes all cache ids. | ||
65 | + * | ||
66 | + * @return string | ||
67 | + */ | ||
68 | + public function getNamespace() | ||
69 | + { | ||
70 | + return $this->namespace; | ||
71 | + } | ||
72 | + | ||
73 | + /** | ||
74 | + * {@inheritdoc} | ||
75 | + */ | ||
76 | + public function fetch($id) | ||
77 | + { | ||
78 | + return $this->doFetch($this->getNamespacedId($id)); | ||
79 | + } | ||
80 | + | ||
81 | + /** | ||
82 | + * {@inheritdoc} | ||
83 | + */ | ||
84 | + public function fetchMultiple(array $keys) | ||
85 | + { | ||
86 | + if (empty($keys)) { | ||
87 | + return array(); | ||
88 | + } | ||
89 | + | ||
90 | + // note: the array_combine() is in place to keep an association between our $keys and the $namespacedKeys | ||
91 | + $namespacedKeys = array_combine($keys, array_map(array($this, 'getNamespacedId'), $keys)); | ||
92 | + $items = $this->doFetchMultiple($namespacedKeys); | ||
93 | + $foundItems = array(); | ||
94 | + | ||
95 | + // no internal array function supports this sort of mapping: needs to be iterative | ||
96 | + // this filters and combines keys in one pass | ||
97 | + foreach ($namespacedKeys as $requestedKey => $namespacedKey) { | ||
98 | + if (isset($items[$namespacedKey]) || array_key_exists($namespacedKey, $items)) { | ||
99 | + $foundItems[$requestedKey] = $items[$namespacedKey]; | ||
100 | + } | ||
101 | + } | ||
102 | + | ||
103 | + return $foundItems; | ||
104 | + } | ||
105 | + | ||
106 | + /** | ||
107 | + * {@inheritdoc} | ||
108 | + */ | ||
109 | + public function contains($id) | ||
110 | + { | ||
111 | + return $this->doContains($this->getNamespacedId($id)); | ||
112 | + } | ||
113 | + | ||
114 | + /** | ||
115 | + * {@inheritdoc} | ||
116 | + */ | ||
117 | + public function save($id, $data, $lifeTime = 0) | ||
118 | + { | ||
119 | + return $this->doSave($this->getNamespacedId($id), $data, $lifeTime); | ||
120 | + } | ||
121 | + | ||
122 | + /** | ||
123 | + * {@inheritdoc} | ||
124 | + */ | ||
125 | + public function delete($id) | ||
126 | + { | ||
127 | + return $this->doDelete($this->getNamespacedId($id)); | ||
128 | + } | ||
129 | + | ||
130 | + /** | ||
131 | + * {@inheritdoc} | ||
132 | + */ | ||
133 | + public function getStats() | ||
134 | + { | ||
135 | + return $this->doGetStats(); | ||
136 | + } | ||
137 | + | ||
138 | + /** | ||
139 | + * {@inheritDoc} | ||
140 | + */ | ||
141 | + public function flushAll() | ||
142 | + { | ||
143 | + return $this->doFlush(); | ||
144 | + } | ||
145 | + | ||
146 | + /** | ||
147 | + * {@inheritDoc} | ||
148 | + */ | ||
149 | + public function deleteAll() | ||
150 | + { | ||
151 | + $namespaceCacheKey = $this->getNamespaceCacheKey(); | ||
152 | + $namespaceVersion = $this->getNamespaceVersion() + 1; | ||
153 | + | ||
154 | + if ($this->doSave($namespaceCacheKey, $namespaceVersion)) { | ||
155 | + $this->namespaceVersion = $namespaceVersion; | ||
156 | + | ||
157 | + return true; | ||
158 | + } | ||
159 | + | ||
160 | + return false; | ||
161 | + } | ||
162 | + | ||
163 | + /** | ||
164 | + * Prefixes the passed id with the configured namespace value. | ||
165 | + * | ||
166 | + * @param string $id The id to namespace. | ||
167 | + * | ||
168 | + * @return string The namespaced id. | ||
169 | + */ | ||
170 | + private function getNamespacedId($id) | ||
171 | + { | ||
172 | + $namespaceVersion = $this->getNamespaceVersion(); | ||
173 | + | ||
174 | + return sprintf('%s[%s][%s]', $this->namespace, $id, $namespaceVersion); | ||
175 | + } | ||
176 | + | ||
177 | + /** | ||
178 | + * Returns the namespace cache key. | ||
179 | + * | ||
180 | + * @return string | ||
181 | + */ | ||
182 | + private function getNamespaceCacheKey() | ||
183 | + { | ||
184 | + return sprintf(self::DOCTRINE_NAMESPACE_CACHEKEY, $this->namespace); | ||
185 | + } | ||
186 | + | ||
187 | + /** | ||
188 | + * Returns the namespace version. | ||
189 | + * | ||
190 | + * @return integer | ||
191 | + */ | ||
192 | + private function getNamespaceVersion() | ||
193 | + { | ||
194 | + if (null !== $this->namespaceVersion) { | ||
195 | + return $this->namespaceVersion; | ||
196 | + } | ||
197 | + | ||
198 | + $namespaceCacheKey = $this->getNamespaceCacheKey(); | ||
199 | + $this->namespaceVersion = $this->doFetch($namespaceCacheKey) ?: 1; | ||
200 | + | ||
201 | + return $this->namespaceVersion; | ||
202 | + } | ||
203 | + | ||
204 | + /** | ||
205 | + * Default implementation of doFetchMultiple. Each driver that supports multi-get should owerwrite it. | ||
206 | + * | ||
207 | + * @param array $keys Array of keys to retrieve from cache | ||
208 | + * @return array Array of values retrieved for the given keys. | ||
209 | + */ | ||
210 | + protected function doFetchMultiple(array $keys) | ||
211 | + { | ||
212 | + $returnValues = array(); | ||
213 | + | ||
214 | + foreach ($keys as $index => $key) { | ||
215 | + if (false !== ($item = $this->doFetch($key))) { | ||
216 | + $returnValues[$key] = $item; | ||
217 | + } | ||
218 | + } | ||
219 | + | ||
220 | + return $returnValues; | ||
221 | + } | ||
222 | + | ||
223 | + /** | ||
224 | + * Fetches an entry from the cache. | ||
225 | + * | ||
226 | + * @param string $id The id of the cache entry to fetch. | ||
227 | + * | ||
228 | + * @return mixed|boolean The cached data or FALSE, if no cache entry exists for the given id. | ||
229 | + */ | ||
230 | + abstract protected function doFetch($id); | ||
231 | + | ||
232 | + /** | ||
233 | + * Tests if an entry exists in the cache. | ||
234 | + * | ||
235 | + * @param string $id The cache id of the entry to check for. | ||
236 | + * | ||
237 | + * @return boolean TRUE if a cache entry exists for the given cache id, FALSE otherwise. | ||
238 | + */ | ||
239 | + abstract protected function doContains($id); | ||
240 | + | ||
241 | + /** | ||
242 | + * Puts data into the cache. | ||
243 | + * | ||
244 | + * @param string $id The cache id. | ||
245 | + * @param string $data The cache entry/data. | ||
246 | + * @param int $lifeTime The lifetime. If != 0, sets a specific lifetime for this | ||
247 | + * cache entry (0 => infinite lifeTime). | ||
248 | + * | ||
249 | + * @return boolean TRUE if the entry was successfully stored in the cache, FALSE otherwise. | ||
250 | + */ | ||
251 | + abstract protected function doSave($id, $data, $lifeTime = 0); | ||
252 | + | ||
253 | + /** | ||
254 | + * Deletes a cache entry. | ||
255 | + * | ||
256 | + * @param string $id The cache id. | ||
257 | + * | ||
258 | + * @return boolean TRUE if the cache entry was successfully deleted, FALSE otherwise. | ||
259 | + */ | ||
260 | + abstract protected function doDelete($id); | ||
261 | + | ||
262 | + /** | ||
263 | + * Flushes all cache entries. | ||
264 | + * | ||
265 | + * @return boolean TRUE if the cache entries were successfully flushed, FALSE otherwise. | ||
266 | + */ | ||
267 | + abstract protected function doFlush(); | ||
268 | + | ||
269 | + /** | ||
270 | + * Retrieves cached information from the data store. | ||
271 | + * | ||
272 | + * @since 2.2 | ||
273 | + * | ||
274 | + * @return array|null An associative array with server's statistics if available, NULL otherwise. | ||
275 | + */ | ||
276 | + abstract protected function doGetStats(); | ||
277 | +} |
1 | +<?php | ||
2 | +/* | ||
3 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4 | + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
5 | + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
6 | + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
7 | + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
8 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
9 | + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
10 | + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
11 | + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
12 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
13 | + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
14 | + * | ||
15 | + * This software consists of voluntary contributions made by many individuals | ||
16 | + * and is licensed under the MIT license. For more information, see | ||
17 | + * <http://www.doctrine-project.org>. | ||
18 | + */ | ||
19 | + | ||
20 | +namespace Doctrine\Common\Cache; | ||
21 | + | ||
22 | +/** | ||
23 | + * Cache provider that allows to easily chain multiple cache providers | ||
24 | + * | ||
25 | + * @author Michaël Gallego <mic.gallego@gmail.com> | ||
26 | + */ | ||
27 | +class ChainCache extends CacheProvider | ||
28 | +{ | ||
29 | + /** | ||
30 | + * @var CacheProvider[] | ||
31 | + */ | ||
32 | + private $cacheProviders = array(); | ||
33 | + | ||
34 | + /** | ||
35 | + * Constructor | ||
36 | + * | ||
37 | + * @param CacheProvider[] $cacheProviders | ||
38 | + */ | ||
39 | + public function __construct($cacheProviders = array()) | ||
40 | + { | ||
41 | + $this->cacheProviders = $cacheProviders; | ||
42 | + } | ||
43 | + | ||
44 | + /** | ||
45 | + * {@inheritDoc} | ||
46 | + */ | ||
47 | + public function setNamespace($namespace) | ||
48 | + { | ||
49 | + parent::setNamespace($namespace); | ||
50 | + | ||
51 | + foreach ($this->cacheProviders as $cacheProvider) { | ||
52 | + $cacheProvider->setNamespace($namespace); | ||
53 | + } | ||
54 | + } | ||
55 | + | ||
56 | + /** | ||
57 | + * {@inheritDoc} | ||
58 | + */ | ||
59 | + protected function doFetch($id) | ||
60 | + { | ||
61 | + foreach ($this->cacheProviders as $key => $cacheProvider) { | ||
62 | + if ($cacheProvider->doContains($id)) { | ||
63 | + $value = $cacheProvider->doFetch($id); | ||
64 | + | ||
65 | + // We populate all the previous cache layers (that are assumed to be faster) | ||
66 | + for ($subKey = $key - 1 ; $subKey >= 0 ; $subKey--) { | ||
67 | + $this->cacheProviders[$subKey]->doSave($id, $value); | ||
68 | + } | ||
69 | + | ||
70 | + return $value; | ||
71 | + } | ||
72 | + } | ||
73 | + | ||
74 | + return false; | ||
75 | + } | ||
76 | + | ||
77 | + /** | ||
78 | + * {@inheritDoc} | ||
79 | + */ | ||
80 | + protected function doContains($id) | ||
81 | + { | ||
82 | + foreach ($this->cacheProviders as $cacheProvider) { | ||
83 | + if ($cacheProvider->doContains($id)) { | ||
84 | + return true; | ||
85 | + } | ||
86 | + } | ||
87 | + | ||
88 | + return false; | ||
89 | + } | ||
90 | + | ||
91 | + /** | ||
92 | + * {@inheritDoc} | ||
93 | + */ | ||
94 | + protected function doSave($id, $data, $lifeTime = 0) | ||
95 | + { | ||
96 | + $stored = true; | ||
97 | + | ||
98 | + foreach ($this->cacheProviders as $cacheProvider) { | ||
99 | + $stored = $cacheProvider->doSave($id, $data, $lifeTime) && $stored; | ||
100 | + } | ||
101 | + | ||
102 | + return $stored; | ||
103 | + } | ||
104 | + | ||
105 | + /** | ||
106 | + * {@inheritDoc} | ||
107 | + */ | ||
108 | + protected function doDelete($id) | ||
109 | + { | ||
110 | + $deleted = true; | ||
111 | + | ||
112 | + foreach ($this->cacheProviders as $cacheProvider) { | ||
113 | + $deleted = $cacheProvider->doDelete($id) && $deleted; | ||
114 | + } | ||
115 | + | ||
116 | + return $deleted; | ||
117 | + } | ||
118 | + | ||
119 | + /** | ||
120 | + * {@inheritDoc} | ||
121 | + */ | ||
122 | + protected function doFlush() | ||
123 | + { | ||
124 | + $flushed = true; | ||
125 | + | ||
126 | + foreach ($this->cacheProviders as $cacheProvider) { | ||
127 | + $flushed = $cacheProvider->doFlush() && $flushed; | ||
128 | + } | ||
129 | + | ||
130 | + return $flushed; | ||
131 | + } | ||
132 | + | ||
133 | + /** | ||
134 | + * {@inheritDoc} | ||
135 | + */ | ||
136 | + protected function doGetStats() | ||
137 | + { | ||
138 | + // We return all the stats from all adapters | ||
139 | + $stats = array(); | ||
140 | + | ||
141 | + foreach ($this->cacheProviders as $cacheProvider) { | ||
142 | + $stats[] = $cacheProvider->doGetStats(); | ||
143 | + } | ||
144 | + | ||
145 | + return $stats; | ||
146 | + } | ||
147 | +} |
1 | +<?php | ||
2 | +/* | ||
3 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4 | + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
5 | + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
6 | + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
7 | + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
8 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
9 | + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
10 | + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
11 | + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
12 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
13 | + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
14 | + * | ||
15 | + * This software consists of voluntary contributions made by many individuals | ||
16 | + * and is licensed under the MIT license. For more information, see | ||
17 | + * <http://www.doctrine-project.org>. | ||
18 | + */ | ||
19 | + | ||
20 | +namespace Doctrine\Common\Cache; | ||
21 | + | ||
22 | +/** | ||
23 | + * Interface for cache that can be flushed. | ||
24 | + * | ||
25 | + * Intended to be used for partial clearing of a cache namespace. For a more | ||
26 | + * global "flushing", see {@see FlushableCache}. | ||
27 | + * | ||
28 | + * @link www.doctrine-project.org | ||
29 | + * @since 1.4 | ||
30 | + * @author Adirelle <adirelle@gmail.com> | ||
31 | + */ | ||
32 | +interface ClearableCache | ||
33 | +{ | ||
34 | + /** | ||
35 | + * Deletes all cache entries in the current cache namespace. | ||
36 | + * | ||
37 | + * @return boolean TRUE if the cache entries were successfully deleted, FALSE otherwise. | ||
38 | + */ | ||
39 | + public function deleteAll(); | ||
40 | +} |
1 | +<?php | ||
2 | +/* | ||
3 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4 | + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
5 | + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
6 | + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
7 | + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
8 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
9 | + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
10 | + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
11 | + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
12 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
13 | + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
14 | + * | ||
15 | + * This software consists of voluntary contributions made by many individuals | ||
16 | + * and is licensed under the MIT license. For more information, see | ||
17 | + * <http://www.doctrine-project.org>. | ||
18 | + */ | ||
19 | + | ||
20 | +namespace Doctrine\Common\Cache; | ||
21 | + | ||
22 | +use \Couchbase; | ||
23 | + | ||
24 | +/** | ||
25 | + * Couchbase cache provider. | ||
26 | + * | ||
27 | + * @link www.doctrine-project.org | ||
28 | + * @since 2.4 | ||
29 | + * @author Michael Nitschinger <michael@nitschinger.at> | ||
30 | + */ | ||
31 | +class CouchbaseCache extends CacheProvider | ||
32 | +{ | ||
33 | + /** | ||
34 | + * @var Couchbase|null | ||
35 | + */ | ||
36 | + private $couchbase; | ||
37 | + | ||
38 | + /** | ||
39 | + * Sets the Couchbase instance to use. | ||
40 | + * | ||
41 | + * @param Couchbase $couchbase | ||
42 | + * | ||
43 | + * @return void | ||
44 | + */ | ||
45 | + public function setCouchbase(Couchbase $couchbase) | ||
46 | + { | ||
47 | + $this->couchbase = $couchbase; | ||
48 | + } | ||
49 | + | ||
50 | + /** | ||
51 | + * Gets the Couchbase instance used by the cache. | ||
52 | + * | ||
53 | + * @return Couchbase|null | ||
54 | + */ | ||
55 | + public function getCouchbase() | ||
56 | + { | ||
57 | + return $this->couchbase; | ||
58 | + } | ||
59 | + | ||
60 | + /** | ||
61 | + * {@inheritdoc} | ||
62 | + */ | ||
63 | + protected function doFetch($id) | ||
64 | + { | ||
65 | + return $this->couchbase->get($id) ?: false; | ||
66 | + } | ||
67 | + | ||
68 | + /** | ||
69 | + * {@inheritdoc} | ||
70 | + */ | ||
71 | + protected function doContains($id) | ||
72 | + { | ||
73 | + return (null !== $this->couchbase->get($id)); | ||
74 | + } | ||
75 | + | ||
76 | + /** | ||
77 | + * {@inheritdoc} | ||
78 | + */ | ||
79 | + protected function doSave($id, $data, $lifeTime = 0) | ||
80 | + { | ||
81 | + if ($lifeTime > 30 * 24 * 3600) { | ||
82 | + $lifeTime = time() + $lifeTime; | ||
83 | + } | ||
84 | + return $this->couchbase->set($id, $data, (int) $lifeTime); | ||
85 | + } | ||
86 | + | ||
87 | + /** | ||
88 | + * {@inheritdoc} | ||
89 | + */ | ||
90 | + protected function doDelete($id) | ||
91 | + { | ||
92 | + return $this->couchbase->delete($id); | ||
93 | + } | ||
94 | + | ||
95 | + /** | ||
96 | + * {@inheritdoc} | ||
97 | + */ | ||
98 | + protected function doFlush() | ||
99 | + { | ||
100 | + return $this->couchbase->flush(); | ||
101 | + } | ||
102 | + | ||
103 | + /** | ||
104 | + * {@inheritdoc} | ||
105 | + */ | ||
106 | + protected function doGetStats() | ||
107 | + { | ||
108 | + $stats = $this->couchbase->getStats(); | ||
109 | + $servers = $this->couchbase->getServers(); | ||
110 | + $server = explode(":", $servers[0]); | ||
111 | + $key = $server[0] . ":" . "11210"; | ||
112 | + $stats = $stats[$key]; | ||
113 | + return array( | ||
114 | + Cache::STATS_HITS => $stats['get_hits'], | ||
115 | + Cache::STATS_MISSES => $stats['get_misses'], | ||
116 | + Cache::STATS_UPTIME => $stats['uptime'], | ||
117 | + Cache::STATS_MEMORY_USAGE => $stats['bytes'], | ||
118 | + Cache::STATS_MEMORY_AVAILABLE => $stats['limit_maxbytes'], | ||
119 | + ); | ||
120 | + } | ||
121 | +} |
1 | +<?php | ||
2 | +/* | ||
3 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4 | + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
5 | + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
6 | + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
7 | + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
8 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
9 | + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
10 | + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
11 | + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
12 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
13 | + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
14 | + * | ||
15 | + * This software consists of voluntary contributions made by many individuals | ||
16 | + * and is licensed under the MIT license. For more information, see | ||
17 | + * <http://www.doctrine-project.org>. | ||
18 | + */ | ||
19 | + | ||
20 | +namespace Doctrine\Common\Cache; | ||
21 | + | ||
22 | +/** | ||
23 | + * Base file cache driver. | ||
24 | + * | ||
25 | + * @since 2.3 | ||
26 | + * @author Fabio B. Silva <fabio.bat.silva@gmail.com> | ||
27 | + */ | ||
28 | +abstract class FileCache extends CacheProvider | ||
29 | +{ | ||
30 | + /** | ||
31 | + * The cache directory. | ||
32 | + * | ||
33 | + * @var string | ||
34 | + */ | ||
35 | + protected $directory; | ||
36 | + | ||
37 | + /** | ||
38 | + * The cache file extension. | ||
39 | + * | ||
40 | + * @var string | ||
41 | + */ | ||
42 | + private $extension; | ||
43 | + | ||
44 | + /** | ||
45 | + * @var string[] regular expressions for replacing disallowed characters in file name | ||
46 | + */ | ||
47 | + private $disallowedCharacterPatterns = array( | ||
48 | + '/\-/', // replaced to disambiguate original `-` and `-` derived from replacements | ||
49 | + '/[^a-zA-Z0-9\-_\[\]]/' // also excludes non-ascii chars (not supported, depending on FS) | ||
50 | + ); | ||
51 | + | ||
52 | + /** | ||
53 | + * @var string[] replacements for disallowed file characters | ||
54 | + */ | ||
55 | + private $replacementCharacters = array('__', '-'); | ||
56 | + | ||
57 | + /** | ||
58 | + * @var int | ||
59 | + */ | ||
60 | + private $umask; | ||
61 | + | ||
62 | + /** | ||
63 | + * Constructor. | ||
64 | + * | ||
65 | + * @param string $directory The cache directory. | ||
66 | + * @param string $extension The cache file extension. | ||
67 | + * | ||
68 | + * @throws \InvalidArgumentException | ||
69 | + */ | ||
70 | + public function __construct($directory, $extension = '', $umask = 0002) | ||
71 | + { | ||
72 | + // YES, this needs to be *before* createPathIfNeeded() | ||
73 | + if ( ! is_int($umask)) { | ||
74 | + throw new \InvalidArgumentException(sprintf( | ||
75 | + 'The umask parameter is required to be integer, was: %s', | ||
76 | + gettype($umask) | ||
77 | + )); | ||
78 | + } | ||
79 | + $this->umask = $umask; | ||
80 | + | ||
81 | + if ( ! $this->createPathIfNeeded($directory)) { | ||
82 | + throw new \InvalidArgumentException(sprintf( | ||
83 | + 'The directory "%s" does not exist and could not be created.', | ||
84 | + $directory | ||
85 | + )); | ||
86 | + } | ||
87 | + | ||
88 | + if ( ! is_writable($directory)) { | ||
89 | + throw new \InvalidArgumentException(sprintf( | ||
90 | + 'The directory "%s" is not writable.', | ||
91 | + $directory | ||
92 | + )); | ||
93 | + } | ||
94 | + | ||
95 | + // YES, this needs to be *after* createPathIfNeeded() | ||
96 | + $this->directory = realpath($directory); | ||
97 | + $this->extension = (string) $extension; | ||
98 | + } | ||
99 | + | ||
100 | + /** | ||
101 | + * Gets the cache directory. | ||
102 | + * | ||
103 | + * @return string | ||
104 | + */ | ||
105 | + public function getDirectory() | ||
106 | + { | ||
107 | + return $this->directory; | ||
108 | + } | ||
109 | + | ||
110 | + /** | ||
111 | + * Gets the cache file extension. | ||
112 | + * | ||
113 | + * @return string|null | ||
114 | + */ | ||
115 | + public function getExtension() | ||
116 | + { | ||
117 | + return $this->extension; | ||
118 | + } | ||
119 | + | ||
120 | + /** | ||
121 | + * @param string $id | ||
122 | + * | ||
123 | + * @return string | ||
124 | + */ | ||
125 | + protected function getFilename($id) | ||
126 | + { | ||
127 | + return $this->directory | ||
128 | + . DIRECTORY_SEPARATOR | ||
129 | + . implode(str_split(hash('sha256', $id), 2), DIRECTORY_SEPARATOR) | ||
130 | + . DIRECTORY_SEPARATOR | ||
131 | + . preg_replace($this->disallowedCharacterPatterns, $this->replacementCharacters, $id) | ||
132 | + . $this->extension; | ||
133 | + } | ||
134 | + | ||
135 | + /** | ||
136 | + * {@inheritdoc} | ||
137 | + */ | ||
138 | + protected function doDelete($id) | ||
139 | + { | ||
140 | + $filename = $this->getFilename($id); | ||
141 | + | ||
142 | + return @unlink($filename) || ! file_exists($filename); | ||
143 | + } | ||
144 | + | ||
145 | + /** | ||
146 | + * {@inheritdoc} | ||
147 | + */ | ||
148 | + protected function doFlush() | ||
149 | + { | ||
150 | + foreach ($this->getIterator() as $name => $file) { | ||
151 | + if ($file->isDir()) { | ||
152 | + // Remove the intermediate directories which have been created to balance the tree. It only takes effect | ||
153 | + // if the directory is empty. If several caches share the same directory but with different file extensions, | ||
154 | + // the other ones are not removed. | ||
155 | + @rmdir($name); | ||
156 | + } elseif ($this->isFilenameEndingWithExtension($name)) { | ||
157 | + // If an extension is set, only remove files which end with the given extension. | ||
158 | + // If no extension is set, we have no other choice than removing everything. | ||
159 | + @unlink($name); | ||
160 | + } | ||
161 | + } | ||
162 | + | ||
163 | + return true; | ||
164 | + } | ||
165 | + | ||
166 | + /** | ||
167 | + * {@inheritdoc} | ||
168 | + */ | ||
169 | + protected function doGetStats() | ||
170 | + { | ||
171 | + $usage = 0; | ||
172 | + foreach ($this->getIterator() as $name => $file) { | ||
173 | + if (! $file->isDir() && $this->isFilenameEndingWithExtension($name)) { | ||
174 | + $usage += $file->getSize(); | ||
175 | + } | ||
176 | + } | ||
177 | + | ||
178 | + $free = disk_free_space($this->directory); | ||
179 | + | ||
180 | + return array( | ||
181 | + Cache::STATS_HITS => null, | ||
182 | + Cache::STATS_MISSES => null, | ||
183 | + Cache::STATS_UPTIME => null, | ||
184 | + Cache::STATS_MEMORY_USAGE => $usage, | ||
185 | + Cache::STATS_MEMORY_AVAILABLE => $free, | ||
186 | + ); | ||
187 | + } | ||
188 | + | ||
189 | + /** | ||
190 | + * Create path if needed. | ||
191 | + * | ||
192 | + * @param string $path | ||
193 | + * @return bool TRUE on success or if path already exists, FALSE if path cannot be created. | ||
194 | + */ | ||
195 | + private function createPathIfNeeded($path) | ||
196 | + { | ||
197 | + if ( ! is_dir($path)) { | ||
198 | + if (false === @mkdir($path, 0777 & (~$this->umask), true) && !is_dir($path)) { | ||
199 | + return false; | ||
200 | + } | ||
201 | + } | ||
202 | + | ||
203 | + return true; | ||
204 | + } | ||
205 | + | ||
206 | + /** | ||
207 | + * Writes a string content to file in an atomic way. | ||
208 | + * | ||
209 | + * @param string $filename Path to the file where to write the data. | ||
210 | + * @param string $content The content to write | ||
211 | + * | ||
212 | + * @return bool TRUE on success, FALSE if path cannot be created, if path is not writable or an any other error. | ||
213 | + */ | ||
214 | + protected function writeFile($filename, $content) | ||
215 | + { | ||
216 | + $filepath = pathinfo($filename, PATHINFO_DIRNAME); | ||
217 | + | ||
218 | + if ( ! $this->createPathIfNeeded($filepath)) { | ||
219 | + return false; | ||
220 | + } | ||
221 | + | ||
222 | + if ( ! is_writable($filepath)) { | ||
223 | + return false; | ||
224 | + } | ||
225 | + | ||
226 | + $tmpFile = tempnam($filepath, 'swap'); | ||
227 | + @chmod($tmpFile, 0666 & (~$this->umask)); | ||
228 | + | ||
229 | + if (file_put_contents($tmpFile, $content) !== false) { | ||
230 | + if (@rename($tmpFile, $filename)) { | ||
231 | + return true; | ||
232 | + } | ||
233 | + | ||
234 | + @unlink($tmpFile); | ||
235 | + } | ||
236 | + | ||
237 | + return false; | ||
238 | + } | ||
239 | + | ||
240 | + /** | ||
241 | + * @return \Iterator | ||
242 | + */ | ||
243 | + private function getIterator() | ||
244 | + { | ||
245 | + return new \RecursiveIteratorIterator( | ||
246 | + new \RecursiveDirectoryIterator($this->directory, \FilesystemIterator::SKIP_DOTS), | ||
247 | + \RecursiveIteratorIterator::CHILD_FIRST | ||
248 | + ); | ||
249 | + } | ||
250 | + | ||
251 | + /** | ||
252 | + * @param string $name The filename | ||
253 | + * | ||
254 | + * @return bool | ||
255 | + */ | ||
256 | + private function isFilenameEndingWithExtension($name) | ||
257 | + { | ||
258 | + return '' === $this->extension | ||
259 | + || strrpos($name, $this->extension) === (strlen($name) - strlen($this->extension)); | ||
260 | + } | ||
261 | +} |
1 | +<?php | ||
2 | +/* | ||
3 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4 | + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
5 | + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
6 | + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
7 | + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
8 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
9 | + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
10 | + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
11 | + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
12 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
13 | + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
14 | + * | ||
15 | + * This software consists of voluntary contributions made by many individuals | ||
16 | + * and is licensed under the MIT license. For more information, see | ||
17 | + * <http://www.doctrine-project.org>. | ||
18 | + */ | ||
19 | + | ||
20 | +namespace Doctrine\Common\Cache; | ||
21 | + | ||
22 | +/** | ||
23 | + * Filesystem cache driver. | ||
24 | + * | ||
25 | + * @since 2.3 | ||
26 | + * @author Fabio B. Silva <fabio.bat.silva@gmail.com> | ||
27 | + */ | ||
28 | +class FilesystemCache extends FileCache | ||
29 | +{ | ||
30 | + const EXTENSION = '.doctrinecache.data'; | ||
31 | + | ||
32 | + /** | ||
33 | + * {@inheritdoc} | ||
34 | + */ | ||
35 | + public function __construct($directory, $extension = self::EXTENSION, $umask = 0002) | ||
36 | + { | ||
37 | + parent::__construct($directory, $extension, $umask); | ||
38 | + } | ||
39 | + | ||
40 | + /** | ||
41 | + * {@inheritdoc} | ||
42 | + */ | ||
43 | + protected function doFetch($id) | ||
44 | + { | ||
45 | + $data = ''; | ||
46 | + $lifetime = -1; | ||
47 | + $filename = $this->getFilename($id); | ||
48 | + | ||
49 | + if ( ! is_file($filename)) { | ||
50 | + return false; | ||
51 | + } | ||
52 | + | ||
53 | + $resource = fopen($filename, "r"); | ||
54 | + | ||
55 | + if (false !== ($line = fgets($resource))) { | ||
56 | + $lifetime = (int) $line; | ||
57 | + } | ||
58 | + | ||
59 | + if ($lifetime !== 0 && $lifetime < time()) { | ||
60 | + fclose($resource); | ||
61 | + | ||
62 | + return false; | ||
63 | + } | ||
64 | + | ||
65 | + while (false !== ($line = fgets($resource))) { | ||
66 | + $data .= $line; | ||
67 | + } | ||
68 | + | ||
69 | + fclose($resource); | ||
70 | + | ||
71 | + return unserialize($data); | ||
72 | + } | ||
73 | + | ||
74 | + /** | ||
75 | + * {@inheritdoc} | ||
76 | + */ | ||
77 | + protected function doContains($id) | ||
78 | + { | ||
79 | + $lifetime = -1; | ||
80 | + $filename = $this->getFilename($id); | ||
81 | + | ||
82 | + if ( ! is_file($filename)) { | ||
83 | + return false; | ||
84 | + } | ||
85 | + | ||
86 | + $resource = fopen($filename, "r"); | ||
87 | + | ||
88 | + if (false !== ($line = fgets($resource))) { | ||
89 | + $lifetime = (int) $line; | ||
90 | + } | ||
91 | + | ||
92 | + fclose($resource); | ||
93 | + | ||
94 | + return $lifetime === 0 || $lifetime > time(); | ||
95 | + } | ||
96 | + | ||
97 | + /** | ||
98 | + * {@inheritdoc} | ||
99 | + */ | ||
100 | + protected function doSave($id, $data, $lifeTime = 0) | ||
101 | + { | ||
102 | + if ($lifeTime > 0) { | ||
103 | + $lifeTime = time() + $lifeTime; | ||
104 | + } | ||
105 | + | ||
106 | + $data = serialize($data); | ||
107 | + $filename = $this->getFilename($id); | ||
108 | + | ||
109 | + return $this->writeFile($filename, $lifeTime . PHP_EOL . $data); | ||
110 | + } | ||
111 | +} |
1 | +<?php | ||
2 | +/* | ||
3 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4 | + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
5 | + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
6 | + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
7 | + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
8 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
9 | + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
10 | + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
11 | + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
12 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
13 | + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
14 | + * | ||
15 | + * This software consists of voluntary contributions made by many individuals | ||
16 | + * and is licensed under the MIT license. For more information, see | ||
17 | + * <http://www.doctrine-project.org>. | ||
18 | + */ | ||
19 | + | ||
20 | +namespace Doctrine\Common\Cache; | ||
21 | + | ||
22 | +/** | ||
23 | + * Interface for cache that can be flushed. | ||
24 | + * | ||
25 | + * @link www.doctrine-project.org | ||
26 | + * @since 1.4 | ||
27 | + * @author Adirelle <adirelle@gmail.com> | ||
28 | + */ | ||
29 | +interface FlushableCache | ||
30 | +{ | ||
31 | + /** | ||
32 | + * Flushes all cache entries, globally. | ||
33 | + * | ||
34 | + * @return boolean TRUE if the cache entries were successfully flushed, FALSE otherwise. | ||
35 | + */ | ||
36 | + public function flushAll(); | ||
37 | +} |
1 | +<?php | ||
2 | +/* | ||
3 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4 | + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
5 | + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
6 | + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
7 | + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
8 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
9 | + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
10 | + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
11 | + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
12 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
13 | + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
14 | + * | ||
15 | + * This software consists of voluntary contributions made by many individuals | ||
16 | + * and is licensed under the MIT license. For more information, see | ||
17 | + * <http://www.doctrine-project.org>. | ||
18 | + */ | ||
19 | + | ||
20 | +namespace Doctrine\Common\Cache; | ||
21 | + | ||
22 | +use \Memcache; | ||
23 | + | ||
24 | +/** | ||
25 | + * Memcache cache provider. | ||
26 | + * | ||
27 | + * @link www.doctrine-project.org | ||
28 | + * @since 2.0 | ||
29 | + * @author Benjamin Eberlei <kontakt@beberlei.de> | ||
30 | + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> | ||
31 | + * @author Jonathan Wage <jonwage@gmail.com> | ||
32 | + * @author Roman Borschel <roman@code-factory.org> | ||
33 | + * @author David Abdemoulaie <dave@hobodave.com> | ||
34 | + */ | ||
35 | +class MemcacheCache extends CacheProvider | ||
36 | +{ | ||
37 | + /** | ||
38 | + * @var Memcache|null | ||
39 | + */ | ||
40 | + private $memcache; | ||
41 | + | ||
42 | + /** | ||
43 | + * Sets the memcache instance to use. | ||
44 | + * | ||
45 | + * @param Memcache $memcache | ||
46 | + * | ||
47 | + * @return void | ||
48 | + */ | ||
49 | + public function setMemcache(Memcache $memcache) | ||
50 | + { | ||
51 | + $this->memcache = $memcache; | ||
52 | + } | ||
53 | + | ||
54 | + /** | ||
55 | + * Gets the memcache instance used by the cache. | ||
56 | + * | ||
57 | + * @return Memcache|null | ||
58 | + */ | ||
59 | + public function getMemcache() | ||
60 | + { | ||
61 | + return $this->memcache; | ||
62 | + } | ||
63 | + | ||
64 | + /** | ||
65 | + * {@inheritdoc} | ||
66 | + */ | ||
67 | + protected function doFetch($id) | ||
68 | + { | ||
69 | + return $this->memcache->get($id); | ||
70 | + } | ||
71 | + | ||
72 | + /** | ||
73 | + * {@inheritdoc} | ||
74 | + */ | ||
75 | + protected function doContains($id) | ||
76 | + { | ||
77 | + $flags = null; | ||
78 | + $this->memcache->get($id, $flags); | ||
79 | + | ||
80 | + //if memcache has changed the value of "flags", it means the value exists | ||
81 | + return ($flags !== null); | ||
82 | + } | ||
83 | + | ||
84 | + /** | ||
85 | + * {@inheritdoc} | ||
86 | + */ | ||
87 | + protected function doSave($id, $data, $lifeTime = 0) | ||
88 | + { | ||
89 | + if ($lifeTime > 30 * 24 * 3600) { | ||
90 | + $lifeTime = time() + $lifeTime; | ||
91 | + } | ||
92 | + return $this->memcache->set($id, $data, 0, (int) $lifeTime); | ||
93 | + } | ||
94 | + | ||
95 | + /** | ||
96 | + * {@inheritdoc} | ||
97 | + */ | ||
98 | + protected function doDelete($id) | ||
99 | + { | ||
100 | + // Memcache::delete() returns false if entry does not exist | ||
101 | + return $this->memcache->delete($id) || ! $this->doContains($id); | ||
102 | + } | ||
103 | + | ||
104 | + /** | ||
105 | + * {@inheritdoc} | ||
106 | + */ | ||
107 | + protected function doFlush() | ||
108 | + { | ||
109 | + return $this->memcache->flush(); | ||
110 | + } | ||
111 | + | ||
112 | + /** | ||
113 | + * {@inheritdoc} | ||
114 | + */ | ||
115 | + protected function doGetStats() | ||
116 | + { | ||
117 | + $stats = $this->memcache->getStats(); | ||
118 | + return array( | ||
119 | + Cache::STATS_HITS => $stats['get_hits'], | ||
120 | + Cache::STATS_MISSES => $stats['get_misses'], | ||
121 | + Cache::STATS_UPTIME => $stats['uptime'], | ||
122 | + Cache::STATS_MEMORY_USAGE => $stats['bytes'], | ||
123 | + Cache::STATS_MEMORY_AVAILABLE => $stats['limit_maxbytes'], | ||
124 | + ); | ||
125 | + } | ||
126 | +} |
1 | +<?php | ||
2 | +/* | ||
3 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4 | + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
5 | + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
6 | + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
7 | + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
8 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
9 | + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
10 | + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
11 | + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
12 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
13 | + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
14 | + * | ||
15 | + * This software consists of voluntary contributions made by many individuals | ||
16 | + * and is licensed under the MIT license. For more information, see | ||
17 | + * <http://www.doctrine-project.org>. | ||
18 | + */ | ||
19 | + | ||
20 | +namespace Doctrine\Common\Cache; | ||
21 | + | ||
22 | +use \Memcached; | ||
23 | + | ||
24 | +/** | ||
25 | + * Memcached cache provider. | ||
26 | + * | ||
27 | + * @link www.doctrine-project.org | ||
28 | + * @since 2.2 | ||
29 | + * @author Benjamin Eberlei <kontakt@beberlei.de> | ||
30 | + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> | ||
31 | + * @author Jonathan Wage <jonwage@gmail.com> | ||
32 | + * @author Roman Borschel <roman@code-factory.org> | ||
33 | + * @author David Abdemoulaie <dave@hobodave.com> | ||
34 | + */ | ||
35 | +class MemcachedCache extends CacheProvider | ||
36 | +{ | ||
37 | + /** | ||
38 | + * @var Memcached|null | ||
39 | + */ | ||
40 | + private $memcached; | ||
41 | + | ||
42 | + /** | ||
43 | + * Sets the memcache instance to use. | ||
44 | + * | ||
45 | + * @param Memcached $memcached | ||
46 | + * | ||
47 | + * @return void | ||
48 | + */ | ||
49 | + public function setMemcached(Memcached $memcached) | ||
50 | + { | ||
51 | + $this->memcached = $memcached; | ||
52 | + } | ||
53 | + | ||
54 | + /** | ||
55 | + * Gets the memcached instance used by the cache. | ||
56 | + * | ||
57 | + * @return Memcached|null | ||
58 | + */ | ||
59 | + public function getMemcached() | ||
60 | + { | ||
61 | + return $this->memcached; | ||
62 | + } | ||
63 | + | ||
64 | + /** | ||
65 | + * {@inheritdoc} | ||
66 | + */ | ||
67 | + protected function doFetch($id) | ||
68 | + { | ||
69 | + return $this->memcached->get($id); | ||
70 | + } | ||
71 | + | ||
72 | + /** | ||
73 | + * {@inheritdoc} | ||
74 | + */ | ||
75 | + protected function doFetchMultiple(array $keys) | ||
76 | + { | ||
77 | + return $this->memcached->getMulti($keys); | ||
78 | + } | ||
79 | + | ||
80 | + /** | ||
81 | + * {@inheritdoc} | ||
82 | + */ | ||
83 | + protected function doContains($id) | ||
84 | + { | ||
85 | + return false !== $this->memcached->get($id) | ||
86 | + || $this->memcached->getResultCode() !== Memcached::RES_NOTFOUND; | ||
87 | + } | ||
88 | + | ||
89 | + /** | ||
90 | + * {@inheritdoc} | ||
91 | + */ | ||
92 | + protected function doSave($id, $data, $lifeTime = 0) | ||
93 | + { | ||
94 | + if ($lifeTime > 30 * 24 * 3600) { | ||
95 | + $lifeTime = time() + $lifeTime; | ||
96 | + } | ||
97 | + return $this->memcached->set($id, $data, (int) $lifeTime); | ||
98 | + } | ||
99 | + | ||
100 | + /** | ||
101 | + * {@inheritdoc} | ||
102 | + */ | ||
103 | + protected function doDelete($id) | ||
104 | + { | ||
105 | + return $this->memcached->delete($id) | ||
106 | + || $this->memcached->getResultCode() === Memcached::RES_NOTFOUND; | ||
107 | + } | ||
108 | + | ||
109 | + /** | ||
110 | + * {@inheritdoc} | ||
111 | + */ | ||
112 | + protected function doFlush() | ||
113 | + { | ||
114 | + return $this->memcached->flush(); | ||
115 | + } | ||
116 | + | ||
117 | + /** | ||
118 | + * {@inheritdoc} | ||
119 | + */ | ||
120 | + protected function doGetStats() | ||
121 | + { | ||
122 | + $stats = $this->memcached->getStats(); | ||
123 | + $servers = $this->memcached->getServerList(); | ||
124 | + $key = $servers[0]['host'] . ':' . $servers[0]['port']; | ||
125 | + $stats = $stats[$key]; | ||
126 | + return array( | ||
127 | + Cache::STATS_HITS => $stats['get_hits'], | ||
128 | + Cache::STATS_MISSES => $stats['get_misses'], | ||
129 | + Cache::STATS_UPTIME => $stats['uptime'], | ||
130 | + Cache::STATS_MEMORY_USAGE => $stats['bytes'], | ||
131 | + Cache::STATS_MEMORY_AVAILABLE => $stats['limit_maxbytes'], | ||
132 | + ); | ||
133 | + } | ||
134 | +} |
1 | +<?php | ||
2 | +/* | ||
3 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4 | + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
5 | + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
6 | + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
7 | + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
8 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
9 | + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
10 | + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
11 | + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
12 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
13 | + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
14 | + * | ||
15 | + * This software consists of voluntary contributions made by many individuals | ||
16 | + * and is licensed under the MIT license. For more information, see | ||
17 | + * <http://www.doctrine-project.org>. | ||
18 | + */ | ||
19 | + | ||
20 | +namespace Doctrine\Common\Cache; | ||
21 | + | ||
22 | +use MongoBinData; | ||
23 | +use MongoCollection; | ||
24 | +use MongoDate; | ||
25 | + | ||
26 | +/** | ||
27 | + * MongoDB cache provider. | ||
28 | + * | ||
29 | + * @since 1.1 | ||
30 | + * @author Jeremy Mikola <jmikola@gmail.com> | ||
31 | + */ | ||
32 | +class MongoDBCache extends CacheProvider | ||
33 | +{ | ||
34 | + /** | ||
35 | + * The data field will store the serialized PHP value. | ||
36 | + */ | ||
37 | + const DATA_FIELD = 'd'; | ||
38 | + | ||
39 | + /** | ||
40 | + * The expiration field will store a MongoDate value indicating when the | ||
41 | + * cache entry should expire. | ||
42 | + * | ||
43 | + * With MongoDB 2.2+, entries can be automatically deleted by MongoDB by | ||
44 | + * indexing this field with the "expireAfterSeconds" option equal to zero. | ||
45 | + * This will direct MongoDB to regularly query for and delete any entries | ||
46 | + * whose date is older than the current time. Entries without a date value | ||
47 | + * in this field will be ignored. | ||
48 | + * | ||
49 | + * The cache provider will also check dates on its own, in case expired | ||
50 | + * entries are fetched before MongoDB's TTLMonitor pass can expire them. | ||
51 | + * | ||
52 | + * @see http://docs.mongodb.org/manual/tutorial/expire-data/ | ||
53 | + */ | ||
54 | + const EXPIRATION_FIELD = 'e'; | ||
55 | + | ||
56 | + /** | ||
57 | + * @var MongoCollection | ||
58 | + */ | ||
59 | + private $collection; | ||
60 | + | ||
61 | + /** | ||
62 | + * Constructor. | ||
63 | + * | ||
64 | + * This provider will default to the write concern and read preference | ||
65 | + * options set on the MongoCollection instance (or inherited from MongoDB or | ||
66 | + * MongoClient). Using an unacknowledged write concern (< 1) may make the | ||
67 | + * return values of delete() and save() unreliable. Reading from secondaries | ||
68 | + * may make contain() and fetch() unreliable. | ||
69 | + * | ||
70 | + * @see http://www.php.net/manual/en/mongo.readpreferences.php | ||
71 | + * @see http://www.php.net/manual/en/mongo.writeconcerns.php | ||
72 | + * @param MongoCollection $collection | ||
73 | + */ | ||
74 | + public function __construct(MongoCollection $collection) | ||
75 | + { | ||
76 | + $this->collection = $collection; | ||
77 | + } | ||
78 | + | ||
79 | + /** | ||
80 | + * {@inheritdoc} | ||
81 | + */ | ||
82 | + protected function doFetch($id) | ||
83 | + { | ||
84 | + $document = $this->collection->findOne(array('_id' => $id), array(self::DATA_FIELD, self::EXPIRATION_FIELD)); | ||
85 | + | ||
86 | + if ($document === null) { | ||
87 | + return false; | ||
88 | + } | ||
89 | + | ||
90 | + if ($this->isExpired($document)) { | ||
91 | + $this->doDelete($id); | ||
92 | + return false; | ||
93 | + } | ||
94 | + | ||
95 | + return unserialize($document[self::DATA_FIELD]->bin); | ||
96 | + } | ||
97 | + | ||
98 | + /** | ||
99 | + * {@inheritdoc} | ||
100 | + */ | ||
101 | + protected function doContains($id) | ||
102 | + { | ||
103 | + $document = $this->collection->findOne(array('_id' => $id), array(self::EXPIRATION_FIELD)); | ||
104 | + | ||
105 | + if ($document === null) { | ||
106 | + return false; | ||
107 | + } | ||
108 | + | ||
109 | + if ($this->isExpired($document)) { | ||
110 | + $this->doDelete($id); | ||
111 | + return false; | ||
112 | + } | ||
113 | + | ||
114 | + return true; | ||
115 | + } | ||
116 | + | ||
117 | + /** | ||
118 | + * {@inheritdoc} | ||
119 | + */ | ||
120 | + protected function doSave($id, $data, $lifeTime = 0) | ||
121 | + { | ||
122 | + $result = $this->collection->update( | ||
123 | + array('_id' => $id), | ||
124 | + array('$set' => array( | ||
125 | + self::EXPIRATION_FIELD => ($lifeTime > 0 ? new MongoDate(time() + $lifeTime) : null), | ||
126 | + self::DATA_FIELD => new MongoBinData(serialize($data), MongoBinData::BYTE_ARRAY), | ||
127 | + )), | ||
128 | + array('upsert' => true, 'multiple' => false) | ||
129 | + ); | ||
130 | + | ||
131 | + return isset($result['ok']) ? $result['ok'] == 1 : true; | ||
132 | + } | ||
133 | + | ||
134 | + /** | ||
135 | + * {@inheritdoc} | ||
136 | + */ | ||
137 | + protected function doDelete($id) | ||
138 | + { | ||
139 | + $result = $this->collection->remove(array('_id' => $id)); | ||
140 | + | ||
141 | + return isset($result['ok']) ? $result['ok'] == 1 : true; | ||
142 | + } | ||
143 | + | ||
144 | + /** | ||
145 | + * {@inheritdoc} | ||
146 | + */ | ||
147 | + protected function doFlush() | ||
148 | + { | ||
149 | + // Use remove() in lieu of drop() to maintain any collection indexes | ||
150 | + $result = $this->collection->remove(); | ||
151 | + | ||
152 | + return isset($result['ok']) ? $result['ok'] == 1 : true; | ||
153 | + } | ||
154 | + | ||
155 | + /** | ||
156 | + * {@inheritdoc} | ||
157 | + */ | ||
158 | + protected function doGetStats() | ||
159 | + { | ||
160 | + $serverStatus = $this->collection->db->command(array( | ||
161 | + 'serverStatus' => 1, | ||
162 | + 'locks' => 0, | ||
163 | + 'metrics' => 0, | ||
164 | + 'recordStats' => 0, | ||
165 | + 'repl' => 0, | ||
166 | + )); | ||
167 | + | ||
168 | + $collStats = $this->collection->db->command(array('collStats' => 1)); | ||
169 | + | ||
170 | + return array( | ||
171 | + Cache::STATS_HITS => null, | ||
172 | + Cache::STATS_MISSES => null, | ||
173 | + Cache::STATS_UPTIME => (isset($serverStatus['uptime']) ? (int) $serverStatus['uptime'] : null), | ||
174 | + Cache::STATS_MEMORY_USAGE => (isset($collStats['size']) ? (int) $collStats['size'] : null), | ||
175 | + Cache::STATS_MEMORY_AVAILABLE => null, | ||
176 | + ); | ||
177 | + } | ||
178 | + | ||
179 | + /** | ||
180 | + * Check if the document is expired. | ||
181 | + * | ||
182 | + * @param array $document | ||
183 | + * @return boolean | ||
184 | + */ | ||
185 | + private function isExpired(array $document) | ||
186 | + { | ||
187 | + return isset($document[self::EXPIRATION_FIELD]) && | ||
188 | + $document[self::EXPIRATION_FIELD] instanceof MongoDate && | ||
189 | + $document[self::EXPIRATION_FIELD]->sec < time(); | ||
190 | + } | ||
191 | +} |
1 | +<?php | ||
2 | +/* | ||
3 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4 | + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
5 | + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
6 | + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
7 | + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
8 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
9 | + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
10 | + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
11 | + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
12 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
13 | + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
14 | + * | ||
15 | + * This software consists of voluntary contributions made by many individuals | ||
16 | + * and is licensed under the MIT license. For more information, see | ||
17 | + * <http://www.doctrine-project.org>. | ||
18 | + */ | ||
19 | + | ||
20 | +namespace Doctrine\Common\Cache; | ||
21 | + | ||
22 | +/** | ||
23 | + * Interface for cache drivers that allows to get many items at once. | ||
24 | + * | ||
25 | + * @link www.doctrine-project.org | ||
26 | + * @since 1.4 | ||
27 | + * @author Asmir Mustafic <goetas@gmail.com> | ||
28 | + */ | ||
29 | +interface MultiGetCache | ||
30 | +{ | ||
31 | + /** | ||
32 | + * Returns an associative array of values for keys is found in cache. | ||
33 | + * | ||
34 | + * @param string[] $keys Array of keys to retrieve from cache | ||
35 | + * @return mixed[] Array of retrieved values, indexed by the specified keys. | ||
36 | + * Values that couldn't be retrieved are not contained in this array. | ||
37 | + */ | ||
38 | + function fetchMultiple(array $keys); | ||
39 | +} |
1 | +<?php | ||
2 | +/* | ||
3 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4 | + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
5 | + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
6 | + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
7 | + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
8 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
9 | + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
10 | + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
11 | + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
12 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
13 | + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
14 | + * | ||
15 | + * This software consists of voluntary contributions made by many individuals | ||
16 | + * and is licensed under the MIT license. For more information, see | ||
17 | + * <http://www.doctrine-project.org>. | ||
18 | + */ | ||
19 | + | ||
20 | +namespace Doctrine\Common\Cache; | ||
21 | + | ||
22 | +/** | ||
23 | + * Php file cache driver. | ||
24 | + * | ||
25 | + * @since 2.3 | ||
26 | + * @author Fabio B. Silva <fabio.bat.silva@gmail.com> | ||
27 | + */ | ||
28 | +class PhpFileCache extends FileCache | ||
29 | +{ | ||
30 | + const EXTENSION = '.doctrinecache.php'; | ||
31 | + | ||
32 | + /** | ||
33 | + * {@inheritdoc} | ||
34 | + */ | ||
35 | + public function __construct($directory, $extension = self::EXTENSION, $umask = 0002) | ||
36 | + { | ||
37 | + parent::__construct($directory, $extension, $umask); | ||
38 | + } | ||
39 | + | ||
40 | + /** | ||
41 | + * {@inheritdoc} | ||
42 | + */ | ||
43 | + protected function doFetch($id) | ||
44 | + { | ||
45 | + $value = $this->includeFileForId($id); | ||
46 | + | ||
47 | + if (! $value) { | ||
48 | + return false; | ||
49 | + } | ||
50 | + | ||
51 | + if ($value['lifetime'] !== 0 && $value['lifetime'] < time()) { | ||
52 | + return false; | ||
53 | + } | ||
54 | + | ||
55 | + return $value['data']; | ||
56 | + } | ||
57 | + | ||
58 | + /** | ||
59 | + * {@inheritdoc} | ||
60 | + */ | ||
61 | + protected function doContains($id) | ||
62 | + { | ||
63 | + $value = $this->includeFileForId($id); | ||
64 | + | ||
65 | + if (! $value) { | ||
66 | + return false; | ||
67 | + } | ||
68 | + | ||
69 | + return $value['lifetime'] === 0 || $value['lifetime'] > time(); | ||
70 | + } | ||
71 | + | ||
72 | + /** | ||
73 | + * {@inheritdoc} | ||
74 | + */ | ||
75 | + protected function doSave($id, $data, $lifeTime = 0) | ||
76 | + { | ||
77 | + if ($lifeTime > 0) { | ||
78 | + $lifeTime = time() + $lifeTime; | ||
79 | + } | ||
80 | + | ||
81 | + if (is_object($data) && ! method_exists($data, '__set_state')) { | ||
82 | + throw new \InvalidArgumentException( | ||
83 | + "Invalid argument given, PhpFileCache only allows objects that implement __set_state() " . | ||
84 | + "and fully support var_export(). You can use the FilesystemCache to save arbitrary object " . | ||
85 | + "graphs using serialize()/deserialize()." | ||
86 | + ); | ||
87 | + } | ||
88 | + | ||
89 | + $filename = $this->getFilename($id); | ||
90 | + | ||
91 | + $value = array( | ||
92 | + 'lifetime' => $lifeTime, | ||
93 | + 'data' => $data | ||
94 | + ); | ||
95 | + | ||
96 | + $value = var_export($value, true); | ||
97 | + $code = sprintf('<?php return %s;', $value); | ||
98 | + | ||
99 | + return $this->writeFile($filename, $code); | ||
100 | + } | ||
101 | + | ||
102 | + /** | ||
103 | + * @param string $id | ||
104 | + * | ||
105 | + * @return array|false | ||
106 | + */ | ||
107 | + private function includeFileForId($id) | ||
108 | + { | ||
109 | + $fileName = $this->getFilename($id); | ||
110 | + | ||
111 | + // note: error suppression is still faster than `file_exists`, `is_file` and `is_readable` | ||
112 | + $value = @include $fileName; | ||
113 | + | ||
114 | + if (! isset($value['lifetime'])) { | ||
115 | + return false; | ||
116 | + } | ||
117 | + | ||
118 | + return $value; | ||
119 | + } | ||
120 | +} |
1 | +<?php | ||
2 | + | ||
3 | +namespace Doctrine\Common\Cache; | ||
4 | + | ||
5 | +use Predis\Client; | ||
6 | + | ||
7 | +/** | ||
8 | + * Predis cache provider. | ||
9 | + * | ||
10 | + * @author othillo <othillo@othillo.nl> | ||
11 | + */ | ||
12 | +class PredisCache extends CacheProvider | ||
13 | +{ | ||
14 | + /** | ||
15 | + * @var Client | ||
16 | + */ | ||
17 | + private $client; | ||
18 | + | ||
19 | + /** | ||
20 | + * @param Client $client | ||
21 | + * | ||
22 | + * @return void | ||
23 | + */ | ||
24 | + public function __construct(Client $client) | ||
25 | + { | ||
26 | + $this->client = $client; | ||
27 | + } | ||
28 | + | ||
29 | + /** | ||
30 | + * {@inheritdoc} | ||
31 | + */ | ||
32 | + protected function doFetch($id) | ||
33 | + { | ||
34 | + $result = $this->client->get($id); | ||
35 | + if (null === $result) { | ||
36 | + return false; | ||
37 | + } | ||
38 | + | ||
39 | + return unserialize($result); | ||
40 | + } | ||
41 | + | ||
42 | + /** | ||
43 | + * {@inheritdoc} | ||
44 | + */ | ||
45 | + protected function doFetchMultiple(array $keys) | ||
46 | + { | ||
47 | + $fetchedItems = call_user_func_array(array($this->client, 'mget'), $keys); | ||
48 | + | ||
49 | + return array_map('unserialize', array_filter(array_combine($keys, $fetchedItems))); | ||
50 | + } | ||
51 | + | ||
52 | + /** | ||
53 | + * {@inheritdoc} | ||
54 | + */ | ||
55 | + protected function doContains($id) | ||
56 | + { | ||
57 | + return $this->client->exists($id); | ||
58 | + } | ||
59 | + | ||
60 | + /** | ||
61 | + * {@inheritdoc} | ||
62 | + */ | ||
63 | + protected function doSave($id, $data, $lifeTime = 0) | ||
64 | + { | ||
65 | + $data = serialize($data); | ||
66 | + if ($lifeTime > 0) { | ||
67 | + $response = $this->client->setex($id, $lifeTime, $data); | ||
68 | + } else { | ||
69 | + $response = $this->client->set($id, $data); | ||
70 | + } | ||
71 | + | ||
72 | + return $response === true || $response == 'OK'; | ||
73 | + } | ||
74 | + | ||
75 | + /** | ||
76 | + * {@inheritdoc} | ||
77 | + */ | ||
78 | + protected function doDelete($id) | ||
79 | + { | ||
80 | + return $this->client->del($id) >= 0; | ||
81 | + } | ||
82 | + | ||
83 | + /** | ||
84 | + * {@inheritdoc} | ||
85 | + */ | ||
86 | + protected function doFlush() | ||
87 | + { | ||
88 | + $response = $this->client->flushdb(); | ||
89 | + | ||
90 | + return $response === true || $response == 'OK'; | ||
91 | + } | ||
92 | + | ||
93 | + /** | ||
94 | + * {@inheritdoc} | ||
95 | + */ | ||
96 | + protected function doGetStats() | ||
97 | + { | ||
98 | + $info = $this->client->info(); | ||
99 | + | ||
100 | + return array( | ||
101 | + Cache::STATS_HITS => $info['Stats']['keyspace_hits'], | ||
102 | + Cache::STATS_MISSES => $info['Stats']['keyspace_misses'], | ||
103 | + Cache::STATS_UPTIME => $info['Server']['uptime_in_seconds'], | ||
104 | + Cache::STATS_MEMORY_USAGE => $info['Memory']['used_memory'], | ||
105 | + Cache::STATS_MEMORY_AVAILABLE => false | ||
106 | + ); | ||
107 | + } | ||
108 | +} |
1 | +<?php | ||
2 | +/* | ||
3 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4 | + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
5 | + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
6 | + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
7 | + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
8 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
9 | + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
10 | + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
11 | + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
12 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
13 | + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
14 | + * | ||
15 | + * This software consists of voluntary contributions made by many individuals | ||
16 | + * and is licensed under the MIT license. For more information, see | ||
17 | + * <http://www.doctrine-project.org>. | ||
18 | + */ | ||
19 | + | ||
20 | +namespace Doctrine\Common\Cache; | ||
21 | + | ||
22 | +use Redis; | ||
23 | + | ||
24 | +/** | ||
25 | + * Redis cache provider. | ||
26 | + * | ||
27 | + * @link www.doctrine-project.org | ||
28 | + * @since 2.2 | ||
29 | + * @author Osman Ungur <osmanungur@gmail.com> | ||
30 | + */ | ||
31 | +class RedisCache extends CacheProvider | ||
32 | +{ | ||
33 | + /** | ||
34 | + * @var Redis|null | ||
35 | + */ | ||
36 | + private $redis; | ||
37 | + | ||
38 | + /** | ||
39 | + * Sets the redis instance to use. | ||
40 | + * | ||
41 | + * @param Redis $redis | ||
42 | + * | ||
43 | + * @return void | ||
44 | + */ | ||
45 | + public function setRedis(Redis $redis) | ||
46 | + { | ||
47 | + $redis->setOption(Redis::OPT_SERIALIZER, $this->getSerializerValue()); | ||
48 | + $this->redis = $redis; | ||
49 | + } | ||
50 | + | ||
51 | + /** | ||
52 | + * Gets the redis instance used by the cache. | ||
53 | + * | ||
54 | + * @return Redis|null | ||
55 | + */ | ||
56 | + public function getRedis() | ||
57 | + { | ||
58 | + return $this->redis; | ||
59 | + } | ||
60 | + | ||
61 | + /** | ||
62 | + * {@inheritdoc} | ||
63 | + */ | ||
64 | + protected function doFetch($id) | ||
65 | + { | ||
66 | + return $this->redis->get($id); | ||
67 | + } | ||
68 | + | ||
69 | + /** | ||
70 | + * {@inheritdoc} | ||
71 | + */ | ||
72 | + protected function doFetchMultiple(array $keys) | ||
73 | + { | ||
74 | + $fetchedItems = $this->redis->mget($keys); | ||
75 | + | ||
76 | + return array_filter( | ||
77 | + array_combine($keys, $fetchedItems), | ||
78 | + function ($value) { | ||
79 | + return $value !== false; | ||
80 | + } | ||
81 | + ); | ||
82 | + } | ||
83 | + | ||
84 | + /** | ||
85 | + * {@inheritdoc} | ||
86 | + */ | ||
87 | + protected function doContains($id) | ||
88 | + { | ||
89 | + return $this->redis->exists($id); | ||
90 | + } | ||
91 | + | ||
92 | + /** | ||
93 | + * {@inheritdoc} | ||
94 | + */ | ||
95 | + protected function doSave($id, $data, $lifeTime = 0) | ||
96 | + { | ||
97 | + if ($lifeTime > 0) { | ||
98 | + return $this->redis->setex($id, $lifeTime, $data); | ||
99 | + } | ||
100 | + | ||
101 | + return $this->redis->set($id, $data); | ||
102 | + } | ||
103 | + | ||
104 | + /** | ||
105 | + * {@inheritdoc} | ||
106 | + */ | ||
107 | + protected function doDelete($id) | ||
108 | + { | ||
109 | + return $this->redis->delete($id) >= 0; | ||
110 | + } | ||
111 | + | ||
112 | + /** | ||
113 | + * {@inheritdoc} | ||
114 | + */ | ||
115 | + protected function doFlush() | ||
116 | + { | ||
117 | + return $this->redis->flushDB(); | ||
118 | + } | ||
119 | + | ||
120 | + /** | ||
121 | + * {@inheritdoc} | ||
122 | + */ | ||
123 | + protected function doGetStats() | ||
124 | + { | ||
125 | + $info = $this->redis->info(); | ||
126 | + return array( | ||
127 | + Cache::STATS_HITS => $info['keyspace_hits'], | ||
128 | + Cache::STATS_MISSES => $info['keyspace_misses'], | ||
129 | + Cache::STATS_UPTIME => $info['uptime_in_seconds'], | ||
130 | + Cache::STATS_MEMORY_USAGE => $info['used_memory'], | ||
131 | + Cache::STATS_MEMORY_AVAILABLE => false | ||
132 | + ); | ||
133 | + } | ||
134 | + | ||
135 | + /** | ||
136 | + * Returns the serializer constant to use. If Redis is compiled with | ||
137 | + * igbinary support, that is used. Otherwise the default PHP serializer is | ||
138 | + * used. | ||
139 | + * | ||
140 | + * @return integer One of the Redis::SERIALIZER_* constants | ||
141 | + */ | ||
142 | + protected function getSerializerValue() | ||
143 | + { | ||
144 | + if (defined('HHVM_VERSION')) { | ||
145 | + return Redis::SERIALIZER_PHP; | ||
146 | + } | ||
147 | + return defined('Redis::SERIALIZER_IGBINARY') ? Redis::SERIALIZER_IGBINARY : Redis::SERIALIZER_PHP; | ||
148 | + } | ||
149 | +} |
1 | +<?php | ||
2 | +/* | ||
3 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4 | + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
5 | + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
6 | + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
7 | + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
8 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
9 | + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
10 | + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
11 | + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
12 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
13 | + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
14 | + * | ||
15 | + * This software consists of voluntary contributions made by many individuals | ||
16 | + * and is licensed under the MIT license. For more information, see | ||
17 | + * <http://www.doctrine-project.org>. | ||
18 | + */ | ||
19 | + | ||
20 | +namespace Doctrine\Common\Cache; | ||
21 | + | ||
22 | +use Riak\Bucket; | ||
23 | +use Riak\Connection; | ||
24 | +use Riak\Input; | ||
25 | +use Riak\Exception; | ||
26 | +use Riak\Object; | ||
27 | + | ||
28 | +/** | ||
29 | + * Riak cache provider. | ||
30 | + * | ||
31 | + * @link www.doctrine-project.org | ||
32 | + * @since 1.1 | ||
33 | + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> | ||
34 | + */ | ||
35 | +class RiakCache extends CacheProvider | ||
36 | +{ | ||
37 | + const EXPIRES_HEADER = 'X-Riak-Meta-Expires'; | ||
38 | + | ||
39 | + /** | ||
40 | + * @var \Riak\Bucket | ||
41 | + */ | ||
42 | + private $bucket; | ||
43 | + | ||
44 | + /** | ||
45 | + * Sets the riak bucket instance to use. | ||
46 | + * | ||
47 | + * @param \Riak\Bucket $bucket | ||
48 | + */ | ||
49 | + public function __construct(Bucket $bucket) | ||
50 | + { | ||
51 | + $this->bucket = $bucket; | ||
52 | + } | ||
53 | + | ||
54 | + /** | ||
55 | + * {@inheritdoc} | ||
56 | + */ | ||
57 | + protected function doFetch($id) | ||
58 | + { | ||
59 | + try { | ||
60 | + $response = $this->bucket->get($id); | ||
61 | + | ||
62 | + // No objects found | ||
63 | + if ( ! $response->hasObject()) { | ||
64 | + return false; | ||
65 | + } | ||
66 | + | ||
67 | + // Check for attempted siblings | ||
68 | + $object = ($response->hasSiblings()) | ||
69 | + ? $this->resolveConflict($id, $response->getVClock(), $response->getObjectList()) | ||
70 | + : $response->getFirstObject(); | ||
71 | + | ||
72 | + // Check for expired object | ||
73 | + if ($this->isExpired($object)) { | ||
74 | + $this->bucket->delete($object); | ||
75 | + | ||
76 | + return false; | ||
77 | + } | ||
78 | + | ||
79 | + return unserialize($object->getContent()); | ||
80 | + } catch (Exception\RiakException $e) { | ||
81 | + // Covers: | ||
82 | + // - Riak\ConnectionException | ||
83 | + // - Riak\CommunicationException | ||
84 | + // - Riak\UnexpectedResponseException | ||
85 | + // - Riak\NotFoundException | ||
86 | + } | ||
87 | + | ||
88 | + return false; | ||
89 | + } | ||
90 | + | ||
91 | + /** | ||
92 | + * {@inheritdoc} | ||
93 | + */ | ||
94 | + protected function doContains($id) | ||
95 | + { | ||
96 | + try { | ||
97 | + // We only need the HEAD, not the entire object | ||
98 | + $input = new Input\GetInput(); | ||
99 | + | ||
100 | + $input->setReturnHead(true); | ||
101 | + | ||
102 | + $response = $this->bucket->get($id, $input); | ||
103 | + | ||
104 | + // No objects found | ||
105 | + if ( ! $response->hasObject()) { | ||
106 | + return false; | ||
107 | + } | ||
108 | + | ||
109 | + $object = $response->getFirstObject(); | ||
110 | + | ||
111 | + // Check for expired object | ||
112 | + if ($this->isExpired($object)) { | ||
113 | + $this->bucket->delete($object); | ||
114 | + | ||
115 | + return false; | ||
116 | + } | ||
117 | + | ||
118 | + return true; | ||
119 | + } catch (Exception\RiakException $e) { | ||
120 | + // Do nothing | ||
121 | + } | ||
122 | + | ||
123 | + return false; | ||
124 | + } | ||
125 | + | ||
126 | + /** | ||
127 | + * {@inheritdoc} | ||
128 | + */ | ||
129 | + protected function doSave($id, $data, $lifeTime = 0) | ||
130 | + { | ||
131 | + try { | ||
132 | + $object = new Object($id); | ||
133 | + | ||
134 | + $object->setContent(serialize($data)); | ||
135 | + | ||
136 | + if ($lifeTime > 0) { | ||
137 | + $object->addMetadata(self::EXPIRES_HEADER, (string) (time() + $lifeTime)); | ||
138 | + } | ||
139 | + | ||
140 | + $this->bucket->put($object); | ||
141 | + | ||
142 | + return true; | ||
143 | + } catch (Exception\RiakException $e) { | ||
144 | + // Do nothing | ||
145 | + } | ||
146 | + | ||
147 | + return false; | ||
148 | + } | ||
149 | + | ||
150 | + /** | ||
151 | + * {@inheritdoc} | ||
152 | + */ | ||
153 | + protected function doDelete($id) | ||
154 | + { | ||
155 | + try { | ||
156 | + $this->bucket->delete($id); | ||
157 | + | ||
158 | + return true; | ||
159 | + } catch (Exception\BadArgumentsException $e) { | ||
160 | + // Key did not exist on cluster already | ||
161 | + } catch (Exception\RiakException $e) { | ||
162 | + // Covers: | ||
163 | + // - Riak\Exception\ConnectionException | ||
164 | + // - Riak\Exception\CommunicationException | ||
165 | + // - Riak\Exception\UnexpectedResponseException | ||
166 | + } | ||
167 | + | ||
168 | + return false; | ||
169 | + } | ||
170 | + | ||
171 | + /** | ||
172 | + * {@inheritdoc} | ||
173 | + */ | ||
174 | + protected function doFlush() | ||
175 | + { | ||
176 | + try { | ||
177 | + $keyList = $this->bucket->getKeyList(); | ||
178 | + | ||
179 | + foreach ($keyList as $key) { | ||
180 | + $this->bucket->delete($key); | ||
181 | + } | ||
182 | + | ||
183 | + return true; | ||
184 | + } catch (Exception\RiakException $e) { | ||
185 | + // Do nothing | ||
186 | + } | ||
187 | + | ||
188 | + return false; | ||
189 | + } | ||
190 | + | ||
191 | + /** | ||
192 | + * {@inheritdoc} | ||
193 | + */ | ||
194 | + protected function doGetStats() | ||
195 | + { | ||
196 | + // Only exposed through HTTP stats API, not Protocol Buffers API | ||
197 | + return null; | ||
198 | + } | ||
199 | + | ||
200 | + /** | ||
201 | + * Check if a given Riak Object have expired. | ||
202 | + * | ||
203 | + * @param \Riak\Object $object | ||
204 | + * | ||
205 | + * @return boolean | ||
206 | + */ | ||
207 | + private function isExpired(Object $object) | ||
208 | + { | ||
209 | + $metadataMap = $object->getMetadataMap(); | ||
210 | + | ||
211 | + return isset($metadataMap[self::EXPIRES_HEADER]) | ||
212 | + && $metadataMap[self::EXPIRES_HEADER] < time(); | ||
213 | + } | ||
214 | + | ||
215 | + /** | ||
216 | + * On-read conflict resolution. Applied approach here is last write wins. | ||
217 | + * Specific needs may override this method to apply alternate conflict resolutions. | ||
218 | + * | ||
219 | + * {@internal Riak does not attempt to resolve a write conflict, and store | ||
220 | + * it as sibling of conflicted one. By following this approach, it is up to | ||
221 | + * the next read to resolve the conflict. When this happens, your fetched | ||
222 | + * object will have a list of siblings (read as a list of objects). | ||
223 | + * In our specific case, we do not care about the intermediate ones since | ||
224 | + * they are all the same read from storage, and we do apply a last sibling | ||
225 | + * (last write) wins logic. | ||
226 | + * If by any means our resolution generates another conflict, it'll up to | ||
227 | + * next read to properly solve it.} | ||
228 | + * | ||
229 | + * @param string $id | ||
230 | + * @param string $vClock | ||
231 | + * @param array $objectList | ||
232 | + * | ||
233 | + * @return \Riak\Object | ||
234 | + */ | ||
235 | + protected function resolveConflict($id, $vClock, array $objectList) | ||
236 | + { | ||
237 | + // Our approach here is last-write wins | ||
238 | + $winner = $objectList[count($objectList)]; | ||
239 | + | ||
240 | + $putInput = new Input\PutInput(); | ||
241 | + $putInput->setVClock($vClock); | ||
242 | + | ||
243 | + $mergedObject = new Object($id); | ||
244 | + $mergedObject->setContent($winner->getContent()); | ||
245 | + | ||
246 | + $this->bucket->put($mergedObject, $putInput); | ||
247 | + | ||
248 | + return $mergedObject; | ||
249 | + } | ||
250 | +} |
1 | +<?php | ||
2 | +/* | ||
3 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4 | + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
5 | + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
6 | + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
7 | + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
8 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
9 | + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
10 | + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
11 | + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
12 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
13 | + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
14 | + * | ||
15 | + * This software consists of voluntary contributions made by many individuals | ||
16 | + * and is licensed under the MIT license. For more information, see | ||
17 | + * <http://www.doctrine-project.org>. | ||
18 | + */ | ||
19 | + | ||
20 | +namespace Doctrine\Common\Cache; | ||
21 | + | ||
22 | +use SQLite3; | ||
23 | +use SQLite3Result; | ||
24 | + | ||
25 | +/** | ||
26 | + * SQLite3 cache provider. | ||
27 | + * | ||
28 | + * @since 1.4 | ||
29 | + * @author Jake Bell <jake@theunraveler.com> | ||
30 | + */ | ||
31 | +class SQLite3Cache extends CacheProvider | ||
32 | +{ | ||
33 | + /** | ||
34 | + * The ID field will store the cache key. | ||
35 | + */ | ||
36 | + const ID_FIELD = 'k'; | ||
37 | + | ||
38 | + /** | ||
39 | + * The data field will store the serialized PHP value. | ||
40 | + */ | ||
41 | + const DATA_FIELD = 'd'; | ||
42 | + | ||
43 | + /** | ||
44 | + * The expiration field will store a date value indicating when the | ||
45 | + * cache entry should expire. | ||
46 | + */ | ||
47 | + const EXPIRATION_FIELD = 'e'; | ||
48 | + | ||
49 | + /** | ||
50 | + * @var SQLite3 | ||
51 | + */ | ||
52 | + private $sqlite; | ||
53 | + | ||
54 | + /** | ||
55 | + * @var string | ||
56 | + */ | ||
57 | + private $table; | ||
58 | + | ||
59 | + /** | ||
60 | + * Constructor. | ||
61 | + * | ||
62 | + * Calling the constructor will ensure that the database file and table | ||
63 | + * exist and will create both if they don't. | ||
64 | + * | ||
65 | + * @param SQLite3 $sqlite | ||
66 | + * @param string $table | ||
67 | + */ | ||
68 | + public function __construct(SQLite3 $sqlite, $table) | ||
69 | + { | ||
70 | + $this->sqlite = $sqlite; | ||
71 | + $this->table = (string) $table; | ||
72 | + | ||
73 | + list($id, $data, $exp) = $this->getFields(); | ||
74 | + | ||
75 | + return $this->sqlite->exec(sprintf( | ||
76 | + 'CREATE TABLE IF NOT EXISTS %s(%s TEXT PRIMARY KEY NOT NULL, %s BLOB, %s INTEGER)', | ||
77 | + $table, | ||
78 | + $id, | ||
79 | + $data, | ||
80 | + $exp | ||
81 | + )); | ||
82 | + } | ||
83 | + | ||
84 | + /** | ||
85 | + * {@inheritdoc} | ||
86 | + */ | ||
87 | + protected function doFetch($id) | ||
88 | + { | ||
89 | + if ($item = $this->findById($id)) { | ||
90 | + return unserialize($item[self::DATA_FIELD]); | ||
91 | + } | ||
92 | + | ||
93 | + return false; | ||
94 | + } | ||
95 | + | ||
96 | + /** | ||
97 | + * {@inheritdoc} | ||
98 | + */ | ||
99 | + protected function doContains($id) | ||
100 | + { | ||
101 | + return (boolean) $this->findById($id, false); | ||
102 | + } | ||
103 | + | ||
104 | + /** | ||
105 | + * {@inheritdoc} | ||
106 | + */ | ||
107 | + protected function doSave($id, $data, $lifeTime = 0) | ||
108 | + { | ||
109 | + $statement = $this->sqlite->prepare(sprintf( | ||
110 | + 'INSERT OR REPLACE INTO %s (%s) VALUES (:id, :data, :expire)', | ||
111 | + $this->table, | ||
112 | + implode(',', $this->getFields()) | ||
113 | + )); | ||
114 | + | ||
115 | + $statement->bindValue(':id', $id); | ||
116 | + $statement->bindValue(':data', serialize($data), SQLITE3_BLOB); | ||
117 | + $statement->bindValue(':expire', $lifeTime > 0 ? time() + $lifeTime : null); | ||
118 | + | ||
119 | + return $statement->execute() instanceof SQLite3Result; | ||
120 | + } | ||
121 | + | ||
122 | + /** | ||
123 | + * {@inheritdoc} | ||
124 | + */ | ||
125 | + protected function doDelete($id) | ||
126 | + { | ||
127 | + list($idField) = $this->getFields(); | ||
128 | + | ||
129 | + $statement = $this->sqlite->prepare(sprintf( | ||
130 | + 'DELETE FROM %s WHERE %s = :id', | ||
131 | + $this->table, | ||
132 | + $idField | ||
133 | + )); | ||
134 | + | ||
135 | + $statement->bindValue(':id', $id); | ||
136 | + | ||
137 | + return $statement->execute() instanceof SQLite3Result; | ||
138 | + } | ||
139 | + | ||
140 | + /** | ||
141 | + * {@inheritdoc} | ||
142 | + */ | ||
143 | + protected function doFlush() | ||
144 | + { | ||
145 | + return $this->sqlite->exec(sprintf('DELETE FROM %s', $this->table)); | ||
146 | + } | ||
147 | + | ||
148 | + /** | ||
149 | + * {@inheritdoc} | ||
150 | + */ | ||
151 | + protected function doGetStats() | ||
152 | + { | ||
153 | + // no-op. | ||
154 | + } | ||
155 | + | ||
156 | + /** | ||
157 | + * Find a single row by ID. | ||
158 | + * | ||
159 | + * @param mixed $id | ||
160 | + * @param boolean $includeData | ||
161 | + * | ||
162 | + * @return array|null | ||
163 | + */ | ||
164 | + private function findById($id, $includeData = true) | ||
165 | + { | ||
166 | + list($idField) = $fields = $this->getFields(); | ||
167 | + | ||
168 | + if (!$includeData) { | ||
169 | + $key = array_search(static::DATA_FIELD, $fields); | ||
170 | + unset($fields[$key]); | ||
171 | + } | ||
172 | + | ||
173 | + $statement = $this->sqlite->prepare(sprintf( | ||
174 | + 'SELECT %s FROM %s WHERE %s = :id LIMIT 1', | ||
175 | + implode(',', $fields), | ||
176 | + $this->table, | ||
177 | + $idField | ||
178 | + )); | ||
179 | + | ||
180 | + $statement->bindValue(':id', $id, SQLITE3_TEXT); | ||
181 | + | ||
182 | + $item = $statement->execute()->fetchArray(SQLITE3_ASSOC); | ||
183 | + | ||
184 | + if ($item === false) { | ||
185 | + return null; | ||
186 | + } | ||
187 | + | ||
188 | + if ($this->isExpired($item)) { | ||
189 | + $this->doDelete($id); | ||
190 | + | ||
191 | + return null; | ||
192 | + } | ||
193 | + | ||
194 | + return $item; | ||
195 | + } | ||
196 | + | ||
197 | + /** | ||
198 | + * Gets an array of the fields in our table. | ||
199 | + * | ||
200 | + * @return array | ||
201 | + */ | ||
202 | + private function getFields() | ||
203 | + { | ||
204 | + return array(static::ID_FIELD, static::DATA_FIELD, static::EXPIRATION_FIELD); | ||
205 | + } | ||
206 | + | ||
207 | + /** | ||
208 | + * Check if the item is expired. | ||
209 | + * | ||
210 | + * @param array $item | ||
211 | + * @return boolean | ||
212 | + */ | ||
213 | + private function isExpired(array $item) | ||
214 | + { | ||
215 | + return isset($item[static::EXPIRATION_FIELD]) && | ||
216 | + $item[self::EXPIRATION_FIELD] !== null && | ||
217 | + $item[self::EXPIRATION_FIELD] < time(); | ||
218 | + } | ||
219 | +} |
1 | +<?php | ||
2 | +/* | ||
3 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4 | + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
5 | + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
6 | + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
7 | + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
8 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
9 | + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
10 | + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
11 | + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
12 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
13 | + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
14 | + * | ||
15 | + * This software consists of voluntary contributions made by many individuals | ||
16 | + * and is licensed under the MIT license. For more information, see | ||
17 | + * <http://www.doctrine-project.org>. | ||
18 | + */ | ||
19 | + | ||
20 | +namespace Doctrine\Common\Cache; | ||
21 | + | ||
22 | +class Version | ||
23 | +{ | ||
24 | + const VERSION = '1.4.4'; | ||
25 | +} |
1 | +<?php | ||
2 | +/* | ||
3 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4 | + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
5 | + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
6 | + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
7 | + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
8 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
9 | + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
10 | + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
11 | + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
12 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
13 | + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
14 | + * | ||
15 | + * This software consists of voluntary contributions made by many individuals | ||
16 | + * and is licensed under the MIT license. For more information, see | ||
17 | + * <http://www.doctrine-project.org>. | ||
18 | + */ | ||
19 | + | ||
20 | +namespace Doctrine\Common\Cache; | ||
21 | + | ||
22 | +/** | ||
23 | + * Void cache driver. The cache could be of use in tests where you don`t need to cache anything. | ||
24 | + * | ||
25 | + * @link www.doctrine-project.org | ||
26 | + * @since 1.5 | ||
27 | + * @author Kotlyar Maksim <kotlyar.maksim@gmail.com> | ||
28 | + */ | ||
29 | +class VoidCache extends CacheProvider | ||
30 | +{ | ||
31 | + /** | ||
32 | + * {@inheritDoc} | ||
33 | + */ | ||
34 | + protected function doFetch($id) | ||
35 | + { | ||
36 | + return false; | ||
37 | + } | ||
38 | + | ||
39 | + /** | ||
40 | + * {@inheritDoc} | ||
41 | + */ | ||
42 | + protected function doContains($id) | ||
43 | + { | ||
44 | + return false; | ||
45 | + } | ||
46 | + | ||
47 | + /** | ||
48 | + * {@inheritDoc} | ||
49 | + */ | ||
50 | + protected function doSave($id, $data, $lifeTime = 0) | ||
51 | + { | ||
52 | + return true; | ||
53 | + } | ||
54 | + | ||
55 | + /** | ||
56 | + * {@inheritDoc} | ||
57 | + */ | ||
58 | + protected function doDelete($id) | ||
59 | + { | ||
60 | + return true; | ||
61 | + } | ||
62 | + | ||
63 | + /** | ||
64 | + * {@inheritDoc} | ||
65 | + */ | ||
66 | + protected function doFlush() | ||
67 | + { | ||
68 | + return true; | ||
69 | + } | ||
70 | + | ||
71 | + /** | ||
72 | + * {@inheritDoc} | ||
73 | + */ | ||
74 | + protected function doGetStats() | ||
75 | + { | ||
76 | + return; | ||
77 | + } | ||
78 | +} |
1 | +<?php | ||
2 | +/* | ||
3 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4 | + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
5 | + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
6 | + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
7 | + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
8 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
9 | + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
10 | + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
11 | + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
12 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
13 | + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
14 | + * | ||
15 | + * This software consists of voluntary contributions made by many individuals | ||
16 | + * and is licensed under the MIT license. For more information, see | ||
17 | + * <http://www.doctrine-project.org>. | ||
18 | + */ | ||
19 | + | ||
20 | +namespace Doctrine\Common\Cache; | ||
21 | + | ||
22 | +/** | ||
23 | + * WinCache cache provider. | ||
24 | + * | ||
25 | + * @link www.doctrine-project.org | ||
26 | + * @since 2.2 | ||
27 | + * @author Benjamin Eberlei <kontakt@beberlei.de> | ||
28 | + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> | ||
29 | + * @author Jonathan Wage <jonwage@gmail.com> | ||
30 | + * @author Roman Borschel <roman@code-factory.org> | ||
31 | + * @author David Abdemoulaie <dave@hobodave.com> | ||
32 | + */ | ||
33 | +class WinCacheCache extends CacheProvider | ||
34 | +{ | ||
35 | + /** | ||
36 | + * {@inheritdoc} | ||
37 | + */ | ||
38 | + protected function doFetch($id) | ||
39 | + { | ||
40 | + return wincache_ucache_get($id); | ||
41 | + } | ||
42 | + | ||
43 | + /** | ||
44 | + * {@inheritdoc} | ||
45 | + */ | ||
46 | + protected function doContains($id) | ||
47 | + { | ||
48 | + return wincache_ucache_exists($id); | ||
49 | + } | ||
50 | + | ||
51 | + /** | ||
52 | + * {@inheritdoc} | ||
53 | + */ | ||
54 | + protected function doSave($id, $data, $lifeTime = 0) | ||
55 | + { | ||
56 | + return (bool) wincache_ucache_set($id, $data, (int) $lifeTime); | ||
57 | + } | ||
58 | + | ||
59 | + /** | ||
60 | + * {@inheritdoc} | ||
61 | + */ | ||
62 | + protected function doDelete($id) | ||
63 | + { | ||
64 | + return wincache_ucache_delete($id); | ||
65 | + } | ||
66 | + | ||
67 | + /** | ||
68 | + * {@inheritdoc} | ||
69 | + */ | ||
70 | + protected function doFlush() | ||
71 | + { | ||
72 | + return wincache_ucache_clear(); | ||
73 | + } | ||
74 | + | ||
75 | + /** | ||
76 | + * {@inheritdoc} | ||
77 | + */ | ||
78 | + protected function doGetStats() | ||
79 | + { | ||
80 | + $info = wincache_ucache_info(); | ||
81 | + $meminfo = wincache_ucache_meminfo(); | ||
82 | + | ||
83 | + return array( | ||
84 | + Cache::STATS_HITS => $info['total_hit_count'], | ||
85 | + Cache::STATS_MISSES => $info['total_miss_count'], | ||
86 | + Cache::STATS_UPTIME => $info['total_cache_uptime'], | ||
87 | + Cache::STATS_MEMORY_USAGE => $meminfo['memory_total'], | ||
88 | + Cache::STATS_MEMORY_AVAILABLE => $meminfo['memory_free'], | ||
89 | + ); | ||
90 | + } | ||
91 | +} |
1 | +<?php | ||
2 | +/* | ||
3 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4 | + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
5 | + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
6 | + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
7 | + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
8 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
9 | + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
10 | + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
11 | + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
12 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
13 | + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
14 | + * | ||
15 | + * This software consists of voluntary contributions made by many individuals | ||
16 | + * and is licensed under the MIT license. For more information, see | ||
17 | + * <http://www.doctrine-project.org>. | ||
18 | + */ | ||
19 | + | ||
20 | +namespace Doctrine\Common\Cache; | ||
21 | + | ||
22 | +/** | ||
23 | + * Xcache cache driver. | ||
24 | + * | ||
25 | + * @link www.doctrine-project.org | ||
26 | + * @since 2.0 | ||
27 | + * @author Benjamin Eberlei <kontakt@beberlei.de> | ||
28 | + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> | ||
29 | + * @author Jonathan Wage <jonwage@gmail.com> | ||
30 | + * @author Roman Borschel <roman@code-factory.org> | ||
31 | + * @author David Abdemoulaie <dave@hobodave.com> | ||
32 | + */ | ||
33 | +class XcacheCache extends CacheProvider | ||
34 | +{ | ||
35 | + /** | ||
36 | + * {@inheritdoc} | ||
37 | + */ | ||
38 | + protected function doFetch($id) | ||
39 | + { | ||
40 | + return $this->doContains($id) ? unserialize(xcache_get($id)) : false; | ||
41 | + } | ||
42 | + | ||
43 | + /** | ||
44 | + * {@inheritdoc} | ||
45 | + */ | ||
46 | + protected function doContains($id) | ||
47 | + { | ||
48 | + return xcache_isset($id); | ||
49 | + } | ||
50 | + | ||
51 | + /** | ||
52 | + * {@inheritdoc} | ||
53 | + */ | ||
54 | + protected function doSave($id, $data, $lifeTime = 0) | ||
55 | + { | ||
56 | + return xcache_set($id, serialize($data), (int) $lifeTime); | ||
57 | + } | ||
58 | + | ||
59 | + /** | ||
60 | + * {@inheritdoc} | ||
61 | + */ | ||
62 | + protected function doDelete($id) | ||
63 | + { | ||
64 | + return xcache_unset($id); | ||
65 | + } | ||
66 | + | ||
67 | + /** | ||
68 | + * {@inheritdoc} | ||
69 | + */ | ||
70 | + protected function doFlush() | ||
71 | + { | ||
72 | + $this->checkAuthorization(); | ||
73 | + | ||
74 | + xcache_clear_cache(XC_TYPE_VAR); | ||
75 | + | ||
76 | + return true; | ||
77 | + } | ||
78 | + | ||
79 | + /** | ||
80 | + * Checks that xcache.admin.enable_auth is Off. | ||
81 | + * | ||
82 | + * @return void | ||
83 | + * | ||
84 | + * @throws \BadMethodCallException When xcache.admin.enable_auth is On. | ||
85 | + */ | ||
86 | + protected function checkAuthorization() | ||
87 | + { | ||
88 | + if (ini_get('xcache.admin.enable_auth')) { | ||
89 | + throw new \BadMethodCallException( | ||
90 | + 'To use all features of \Doctrine\Common\Cache\XcacheCache, ' | ||
91 | + . 'you must set "xcache.admin.enable_auth" to "Off" in your php.ini.' | ||
92 | + ); | ||
93 | + } | ||
94 | + } | ||
95 | + | ||
96 | + /** | ||
97 | + * {@inheritdoc} | ||
98 | + */ | ||
99 | + protected function doGetStats() | ||
100 | + { | ||
101 | + $this->checkAuthorization(); | ||
102 | + | ||
103 | + $info = xcache_info(XC_TYPE_VAR, 0); | ||
104 | + return array( | ||
105 | + Cache::STATS_HITS => $info['hits'], | ||
106 | + Cache::STATS_MISSES => $info['misses'], | ||
107 | + Cache::STATS_UPTIME => null, | ||
108 | + Cache::STATS_MEMORY_USAGE => $info['size'], | ||
109 | + Cache::STATS_MEMORY_AVAILABLE => $info['avail'], | ||
110 | + ); | ||
111 | + } | ||
112 | +} |
1 | +<?php | ||
2 | +/* | ||
3 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4 | + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
5 | + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
6 | + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
7 | + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
8 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
9 | + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
10 | + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
11 | + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
12 | + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
13 | + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
14 | + * | ||
15 | + * This software consists of voluntary contributions made by many individuals | ||
16 | + * and is licensed under the MIT license. For more information, see | ||
17 | + * <http://www.doctrine-project.org>. | ||
18 | + */ | ||
19 | + | ||
20 | +namespace Doctrine\Common\Cache; | ||
21 | + | ||
22 | +/** | ||
23 | + * Zend Data Cache cache driver. | ||
24 | + * | ||
25 | + * @link www.doctrine-project.org | ||
26 | + * @since 2.0 | ||
27 | + * @author Ralph Schindler <ralph.schindler@zend.com> | ||
28 | + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> | ||
29 | + */ | ||
30 | +class ZendDataCache extends CacheProvider | ||
31 | +{ | ||
32 | + /** | ||
33 | + * {@inheritdoc} | ||
34 | + */ | ||
35 | + protected function doFetch($id) | ||
36 | + { | ||
37 | + return zend_shm_cache_fetch($id); | ||
38 | + } | ||
39 | + | ||
40 | + /** | ||
41 | + * {@inheritdoc} | ||
42 | + */ | ||
43 | + protected function doContains($id) | ||
44 | + { | ||
45 | + return (false !== zend_shm_cache_fetch($id)); | ||
46 | + } | ||
47 | + | ||
48 | + /** | ||
49 | + * {@inheritdoc} | ||
50 | + */ | ||
51 | + protected function doSave($id, $data, $lifeTime = 0) | ||
52 | + { | ||
53 | + return zend_shm_cache_store($id, $data, $lifeTime); | ||
54 | + } | ||
55 | + | ||
56 | + /** | ||
57 | + * {@inheritdoc} | ||
58 | + */ | ||
59 | + protected function doDelete($id) | ||
60 | + { | ||
61 | + return zend_shm_cache_delete($id); | ||
62 | + } | ||
63 | + | ||
64 | + /** | ||
65 | + * {@inheritdoc} | ||
66 | + */ | ||
67 | + protected function doFlush() | ||
68 | + { | ||
69 | + $namespace = $this->getNamespace(); | ||
70 | + if (empty($namespace)) { | ||
71 | + return zend_shm_cache_clear(); | ||
72 | + } | ||
73 | + return zend_shm_cache_clear($namespace); | ||
74 | + } | ||
75 | + | ||
76 | + /** | ||
77 | + * {@inheritdoc} | ||
78 | + */ | ||
79 | + protected function doGetStats() | ||
80 | + { | ||
81 | + return null; | ||
82 | + } | ||
83 | +} |
vendor/doctrine/cache/phpunit.xml.dist
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | + | ||
3 | +<phpunit backupGlobals="false" | ||
4 | + backupStaticAttributes="false" | ||
5 | + colors="true" | ||
6 | + convertErrorsToExceptions="true" | ||
7 | + convertNoticesToExceptions="true" | ||
8 | + convertWarningsToExceptions="true" | ||
9 | + processIsolation="false" | ||
10 | + stopOnFailure="false" | ||
11 | + syntaxCheck="false" | ||
12 | + bootstrap="./tests/Doctrine/Tests/TestInit.php" | ||
13 | +> | ||
14 | + <testsuites> | ||
15 | + <testsuite name="Doctrine Cache Test Suite"> | ||
16 | + <directory>./tests/Doctrine/</directory> | ||
17 | + </testsuite> | ||
18 | + </testsuites> | ||
19 | + | ||
20 | + <filter> | ||
21 | + <whitelist> | ||
22 | + <directory>./lib/Doctrine/</directory> | ||
23 | + </whitelist> | ||
24 | + </filter> | ||
25 | +</phpunit> |
1 | +<?php | ||
2 | + | ||
3 | +namespace Doctrine\Tests\Common\Cache; | ||
4 | + | ||
5 | +use Doctrine\Common\Cache\ApcCache; | ||
6 | + | ||
7 | +class ApcCacheTest extends CacheTest | ||
8 | +{ | ||
9 | + public function setUp() | ||
10 | + { | ||
11 | + if ( ! extension_loaded('apc') || false === @apc_cache_info()) { | ||
12 | + $this->markTestSkipped('The ' . __CLASS__ .' requires the use of APC'); | ||
13 | + } | ||
14 | + } | ||
15 | + | ||
16 | + protected function _getCacheDriver() | ||
17 | + { | ||
18 | + return new ApcCache(); | ||
19 | + } | ||
20 | +} |
1 | +<?php | ||
2 | + | ||
3 | +namespace Doctrine\Tests\Common\Cache; | ||
4 | + | ||
5 | +use Doctrine\Common\Cache\ArrayCache; | ||
6 | + | ||
7 | +class ArrayCacheTest extends CacheTest | ||
8 | +{ | ||
9 | + protected function _getCacheDriver() | ||
10 | + { | ||
11 | + return new ArrayCache(); | ||
12 | + } | ||
13 | + | ||
14 | + public function testGetStats() | ||
15 | + { | ||
16 | + $cache = $this->_getCacheDriver(); | ||
17 | + $stats = $cache->getStats(); | ||
18 | + | ||
19 | + $this->assertNull($stats); | ||
20 | + } | ||
21 | + | ||
22 | + protected function isSharedStorage() | ||
23 | + { | ||
24 | + return false; | ||
25 | + } | ||
26 | +} |
1 | +<?php | ||
2 | + | ||
3 | +namespace Doctrine\Tests\Common\Cache; | ||
4 | + | ||
5 | +use RecursiveDirectoryIterator; | ||
6 | +use RecursiveIteratorIterator; | ||
7 | + | ||
8 | +abstract class BaseFileCacheTest extends CacheTest | ||
9 | +{ | ||
10 | + protected $directory; | ||
11 | + | ||
12 | + public function testFlushAllRemovesBalancingDirectories() | ||
13 | + { | ||
14 | + $cache = $this->_getCacheDriver(); | ||
15 | + | ||
16 | + $this->assertTrue($cache->save('key1', 1)); | ||
17 | + $this->assertTrue($cache->save('key2', 2)); | ||
18 | + $this->assertTrue($cache->flushAll()); | ||
19 | + | ||
20 | + $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->directory, \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::CHILD_FIRST); | ||
21 | + | ||
22 | + $this->assertCount(0, $iterator); | ||
23 | + } | ||
24 | + | ||
25 | + protected function setUp() | ||
26 | + { | ||
27 | + do { | ||
28 | + $this->directory = sys_get_temp_dir() . '/doctrine_cache_'. uniqid(); | ||
29 | + } while (file_exists($this->directory)); | ||
30 | + } | ||
31 | + | ||
32 | + protected function tearDown() | ||
33 | + { | ||
34 | + if ( ! is_dir($this->directory)) { | ||
35 | + return; | ||
36 | + } | ||
37 | + | ||
38 | + $iterator = new RecursiveDirectoryIterator($this->directory); | ||
39 | + | ||
40 | + foreach (new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::CHILD_FIRST) as $file) { | ||
41 | + if ($file->isFile()) { | ||
42 | + @unlink($file->getRealPath()); | ||
43 | + } elseif ($file->isDir()) { | ||
44 | + @rmdir($file->getRealPath()); | ||
45 | + } | ||
46 | + } | ||
47 | + | ||
48 | + @rmdir($this->directory); | ||
49 | + } | ||
50 | + | ||
51 | + protected function isSharedStorage() | ||
52 | + { | ||
53 | + return false; | ||
54 | + } | ||
55 | +} |
1 | +<?php | ||
2 | + | ||
3 | +namespace Doctrine\Tests\Common\Cache; | ||
4 | + | ||
5 | +class CacheProviderTest extends \Doctrine\Tests\DoctrineTestCase | ||
6 | +{ | ||
7 | + public function testFetchMultiWillFilterNonRequestedKeys() | ||
8 | + { | ||
9 | + /* @var $cache \Doctrine\Common\Cache\CacheProvider|\PHPUnit_Framework_MockObject_MockObject */ | ||
10 | + $cache = $this->getMockForAbstractClass( | ||
11 | + 'Doctrine\Common\Cache\CacheProvider', | ||
12 | + array(), | ||
13 | + '', | ||
14 | + true, | ||
15 | + true, | ||
16 | + true, | ||
17 | + array('doFetchMultiple') | ||
18 | + ); | ||
19 | + | ||
20 | + $cache | ||
21 | + ->expects($this->once()) | ||
22 | + ->method('doFetchMultiple') | ||
23 | + ->will($this->returnValue(array( | ||
24 | + '[foo][1]' => 'bar', | ||
25 | + '[bar][1]' => 'baz', | ||
26 | + '[baz][1]' => 'tab', | ||
27 | + ))); | ||
28 | + | ||
29 | + $this->assertEquals( | ||
30 | + array('foo' => 'bar', 'bar' => 'baz'), | ||
31 | + $cache->fetchMultiple(array('foo', 'bar')) | ||
32 | + ); | ||
33 | + } | ||
34 | + | ||
35 | + public function testFailedDeleteAllDoesNotChangeNamespaceVersion() | ||
36 | + { | ||
37 | + /* @var $cache \Doctrine\Common\Cache\CacheProvider|\PHPUnit_Framework_MockObject_MockObject */ | ||
38 | + $cache = $this->getMockForAbstractClass( | ||
39 | + 'Doctrine\Common\Cache\CacheProvider', | ||
40 | + array(), | ||
41 | + '', | ||
42 | + true, | ||
43 | + true, | ||
44 | + true, | ||
45 | + array('doFetch', 'doSave', 'doContains') | ||
46 | + ); | ||
47 | + | ||
48 | + $cache | ||
49 | + ->expects($this->once()) | ||
50 | + ->method('doFetch') | ||
51 | + ->with('DoctrineNamespaceCacheKey[]') | ||
52 | + ->will($this->returnValue(false)); | ||
53 | + | ||
54 | + // doSave is only called once from deleteAll as we do not need to persist the default version in getNamespaceVersion() | ||
55 | + $cache | ||
56 | + ->expects($this->once()) | ||
57 | + ->method('doSave') | ||
58 | + ->with('DoctrineNamespaceCacheKey[]') | ||
59 | + ->will($this->returnValue(false)); | ||
60 | + | ||
61 | + // After a failed deleteAll() the local namespace version is not increased (still 1). Otherwise all data written afterwards | ||
62 | + // would be lost outside the current instance. | ||
63 | + $cache | ||
64 | + ->expects($this->once()) | ||
65 | + ->method('doContains') | ||
66 | + ->with('[key][1]') | ||
67 | + ->will($this->returnValue(true)); | ||
68 | + | ||
69 | + $this->assertFalse($cache->deleteAll(), 'deleteAll() returns false when saving the namespace version fails'); | ||
70 | + $cache->contains('key'); | ||
71 | + } | ||
72 | +} |
1 | +<?php | ||
2 | + | ||
3 | +namespace Doctrine\Tests\Common\Cache; | ||
4 | + | ||
5 | +use Doctrine\Common\Cache\Cache; | ||
6 | +use ArrayObject; | ||
7 | + | ||
8 | +abstract class CacheTest extends \Doctrine\Tests\DoctrineTestCase | ||
9 | +{ | ||
10 | + /** | ||
11 | + * @dataProvider provideDataToCache | ||
12 | + */ | ||
13 | + public function testSetContainsFetchDelete($value) | ||
14 | + { | ||
15 | + $cache = $this->_getCacheDriver(); | ||
16 | + | ||
17 | + // Test saving a value, checking if it exists, and fetching it back | ||
18 | + $this->assertTrue($cache->save('key', $value)); | ||
19 | + $this->assertTrue($cache->contains('key')); | ||
20 | + if (is_object($value)) { | ||
21 | + $this->assertEquals($value, $cache->fetch('key'), 'Objects retrieved from the cache must be equal but not necessarily the same reference'); | ||
22 | + } else { | ||
23 | + $this->assertSame($value, $cache->fetch('key'), 'Scalar and array data retrieved from the cache must be the same as the original, e.g. same type'); | ||
24 | + } | ||
25 | + | ||
26 | + // Test deleting a value | ||
27 | + $this->assertTrue($cache->delete('key')); | ||
28 | + $this->assertFalse($cache->contains('key')); | ||
29 | + $this->assertFalse($cache->fetch('key')); | ||
30 | + } | ||
31 | + | ||
32 | + /** | ||
33 | + * @dataProvider provideDataToCache | ||
34 | + */ | ||
35 | + public function testUpdateExistingEntry($value) | ||
36 | + { | ||
37 | + $cache = $this->_getCacheDriver(); | ||
38 | + | ||
39 | + $this->assertTrue($cache->save('key', 'old-value')); | ||
40 | + $this->assertTrue($cache->contains('key')); | ||
41 | + | ||
42 | + $this->assertTrue($cache->save('key', $value)); | ||
43 | + $this->assertTrue($cache->contains('key')); | ||
44 | + if (is_object($value)) { | ||
45 | + $this->assertEquals($value, $cache->fetch('key'), 'Objects retrieved from the cache must be equal but not necessarily the same reference'); | ||
46 | + } else { | ||
47 | + $this->assertSame($value, $cache->fetch('key'), 'Scalar and array data retrieved from the cache must be the same as the original, e.g. same type'); | ||
48 | + } | ||
49 | + } | ||
50 | + | ||
51 | + public function testFetchMulti() | ||
52 | + { | ||
53 | + $cache = $this->_getCacheDriver(); | ||
54 | + | ||
55 | + $cache->deleteAll(); | ||
56 | + | ||
57 | + // Test saving some values, checking if it exists, and fetching it back with multiGet | ||
58 | + $this->assertTrue($cache->save('key1', 'value1')); | ||
59 | + $this->assertTrue($cache->save('key2', 'value2')); | ||
60 | + | ||
61 | + $this->assertEquals( | ||
62 | + array('key1' => 'value1', 'key2' => 'value2'), | ||
63 | + $cache->fetchMultiple(array('key1', 'key2')) | ||
64 | + ); | ||
65 | + $this->assertEquals( | ||
66 | + array('key1' => 'value1', 'key2' => 'value2'), | ||
67 | + $cache->fetchMultiple(array('key1', 'key3', 'key2')) | ||
68 | + ); | ||
69 | + $this->assertEquals( | ||
70 | + array('key1' => 'value1', 'key2' => 'value2'), | ||
71 | + $cache->fetchMultiple(array('key1', 'key2', 'key3')) | ||
72 | + ); | ||
73 | + } | ||
74 | + | ||
75 | + public function testFetchMultiWithEmptyKeysArray() | ||
76 | + { | ||
77 | + $cache = $this->_getCacheDriver(); | ||
78 | + | ||
79 | + $this->assertEmpty( | ||
80 | + $cache->fetchMultiple(array()) | ||
81 | + ); | ||
82 | + } | ||
83 | + | ||
84 | + public function testFetchMultiWithFalsey() | ||
85 | + { | ||
86 | + $cache = $this->_getCacheDriver(); | ||
87 | + | ||
88 | + $cache->deleteAll(); | ||
89 | + | ||
90 | + $values = array( | ||
91 | + 'string' => 'str', | ||
92 | + 'integer' => 1, | ||
93 | + 'boolean' => true, | ||
94 | + 'null' => null, | ||
95 | + 'array_empty' => array(), | ||
96 | + 'integer_zero' => 0, | ||
97 | + 'string_empty' => '' | ||
98 | + ); | ||
99 | + foreach ($values AS $key => $value) { | ||
100 | + $cache->save($key, $value); | ||
101 | + } | ||
102 | + | ||
103 | + $this->assertEquals( | ||
104 | + $values, | ||
105 | + $cache->fetchMultiple(array_keys($values)) | ||
106 | + ); | ||
107 | + } | ||
108 | + | ||
109 | + public function provideDataToCache() | ||
110 | + { | ||
111 | + return array( | ||
112 | + 'array' => array(array('one', 2, 3.01)), | ||
113 | + 'string' => array('value'), | ||
114 | + 'integer' => array(1), | ||
115 | + 'float' => array(1.5), | ||
116 | + 'object' => array(new ArrayObject()), | ||
117 | + 'true' => array(true), | ||
118 | + // the following are considered FALSE in boolean context, but caches should still recognize their existence | ||
119 | + 'null' => array(null), | ||
120 | + 'false' => array(false), | ||
121 | + 'array_empty' => array(array()), | ||
122 | + 'string_zero' => array('0'), | ||
123 | + 'integer_zero' => array(0), | ||
124 | + 'float_zero' => array(0.0), | ||
125 | + 'string_empty' => array('') | ||
126 | + ); | ||
127 | + } | ||
128 | + | ||
129 | + public function testDeleteIsSuccessfulWhenKeyDoesNotExist() | ||
130 | + { | ||
131 | + $cache = $this->_getCacheDriver(); | ||
132 | + | ||
133 | + $this->assertFalse($cache->contains('key')); | ||
134 | + $this->assertTrue($cache->delete('key')); | ||
135 | + } | ||
136 | + | ||
137 | + public function testDeleteAll() | ||
138 | + { | ||
139 | + $cache = $this->_getCacheDriver(); | ||
140 | + | ||
141 | + $this->assertTrue($cache->save('key1', 1)); | ||
142 | + $this->assertTrue($cache->save('key2', 2)); | ||
143 | + $this->assertTrue($cache->deleteAll()); | ||
144 | + $this->assertFalse($cache->contains('key1')); | ||
145 | + $this->assertFalse($cache->contains('key2')); | ||
146 | + } | ||
147 | + | ||
148 | + public function testDeleteAllAndNamespaceVersioningBetweenCaches() | ||
149 | + { | ||
150 | + if ( ! $this->isSharedStorage()) { | ||
151 | + $this->markTestSkipped('The ' . __CLASS__ .' does not use shared storage'); | ||
152 | + } | ||
153 | + | ||
154 | + $cache1 = $this->_getCacheDriver(); | ||
155 | + $cache2 = $this->_getCacheDriver(); | ||
156 | + | ||
157 | + $this->assertTrue($cache1->save('key1', 1)); | ||
158 | + $this->assertTrue($cache2->save('key2', 2)); | ||
159 | + | ||
160 | + /* Both providers are initialized with the same namespace version, so | ||
161 | + * they can see entries set by each other. | ||
162 | + */ | ||
163 | + $this->assertTrue($cache1->contains('key1')); | ||
164 | + $this->assertTrue($cache1->contains('key2')); | ||
165 | + $this->assertTrue($cache2->contains('key1')); | ||
166 | + $this->assertTrue($cache2->contains('key2')); | ||
167 | + | ||
168 | + /* Deleting all entries through one provider will only increment the | ||
169 | + * namespace version on that object (and in the cache itself, which new | ||
170 | + * instances will use to initialize). The second provider will retain | ||
171 | + * its original version and still see stale data. | ||
172 | + */ | ||
173 | + $this->assertTrue($cache1->deleteAll()); | ||
174 | + $this->assertFalse($cache1->contains('key1')); | ||
175 | + $this->assertFalse($cache1->contains('key2')); | ||
176 | + $this->assertTrue($cache2->contains('key1')); | ||
177 | + $this->assertTrue($cache2->contains('key2')); | ||
178 | + | ||
179 | + /* A new cache provider should not see the deleted entries, since its | ||
180 | + * namespace version will be initialized. | ||
181 | + */ | ||
182 | + $cache3 = $this->_getCacheDriver(); | ||
183 | + $this->assertFalse($cache3->contains('key1')); | ||
184 | + $this->assertFalse($cache3->contains('key2')); | ||
185 | + } | ||
186 | + | ||
187 | + public function testFlushAll() | ||
188 | + { | ||
189 | + $cache = $this->_getCacheDriver(); | ||
190 | + | ||
191 | + $this->assertTrue($cache->save('key1', 1)); | ||
192 | + $this->assertTrue($cache->save('key2', 2)); | ||
193 | + $this->assertTrue($cache->flushAll()); | ||
194 | + $this->assertFalse($cache->contains('key1')); | ||
195 | + $this->assertFalse($cache->contains('key2')); | ||
196 | + } | ||
197 | + | ||
198 | + public function testFlushAllAndNamespaceVersioningBetweenCaches() | ||
199 | + { | ||
200 | + if ( ! $this->isSharedStorage()) { | ||
201 | + $this->markTestSkipped('The ' . __CLASS__ .' does not use shared storage'); | ||
202 | + } | ||
203 | + | ||
204 | + $cache1 = $this->_getCacheDriver(); | ||
205 | + $cache2 = $this->_getCacheDriver(); | ||
206 | + | ||
207 | + /* Deleting all elements from the first provider should increment its | ||
208 | + * namespace version before saving the first entry. | ||
209 | + */ | ||
210 | + $cache1->deleteAll(); | ||
211 | + $this->assertTrue($cache1->save('key1', 1)); | ||
212 | + | ||
213 | + /* The second provider will be initialized with the same namespace | ||
214 | + * version upon its first save operation. | ||
215 | + */ | ||
216 | + $this->assertTrue($cache2->save('key2', 2)); | ||
217 | + | ||
218 | + /* Both providers have the same namespace version and can see entries | ||
219 | + * set by each other. | ||
220 | + */ | ||
221 | + $this->assertTrue($cache1->contains('key1')); | ||
222 | + $this->assertTrue($cache1->contains('key2')); | ||
223 | + $this->assertTrue($cache2->contains('key1')); | ||
224 | + $this->assertTrue($cache2->contains('key2')); | ||
225 | + | ||
226 | + /* Flushing all entries through one cache will remove all entries from | ||
227 | + * the cache but leave their namespace version as-is. | ||
228 | + */ | ||
229 | + $this->assertTrue($cache1->flushAll()); | ||
230 | + $this->assertFalse($cache1->contains('key1')); | ||
231 | + $this->assertFalse($cache1->contains('key2')); | ||
232 | + $this->assertFalse($cache2->contains('key1')); | ||
233 | + $this->assertFalse($cache2->contains('key2')); | ||
234 | + | ||
235 | + /* Inserting a new entry will use the same, incremented namespace | ||
236 | + * version, and it will be visible to both providers. | ||
237 | + */ | ||
238 | + $this->assertTrue($cache1->save('key1', 1)); | ||
239 | + $this->assertTrue($cache1->contains('key1')); | ||
240 | + $this->assertTrue($cache2->contains('key1')); | ||
241 | + | ||
242 | + /* A new cache provider will be initialized with the original namespace | ||
243 | + * version and not share any visibility with the first two providers. | ||
244 | + */ | ||
245 | + $cache3 = $this->_getCacheDriver(); | ||
246 | + $this->assertFalse($cache3->contains('key1')); | ||
247 | + $this->assertFalse($cache3->contains('key2')); | ||
248 | + $this->assertTrue($cache3->save('key3', 3)); | ||
249 | + $this->assertTrue($cache3->contains('key3')); | ||
250 | + } | ||
251 | + | ||
252 | + public function testNamespace() | ||
253 | + { | ||
254 | + $cache = $this->_getCacheDriver(); | ||
255 | + | ||
256 | + $cache->setNamespace('ns1_'); | ||
257 | + | ||
258 | + $this->assertTrue($cache->save('key1', 1)); | ||
259 | + $this->assertTrue($cache->contains('key1')); | ||
260 | + | ||
261 | + $cache->setNamespace('ns2_'); | ||
262 | + | ||
263 | + $this->assertFalse($cache->contains('key1')); | ||
264 | + } | ||
265 | + | ||
266 | + public function testDeleteAllNamespace() | ||
267 | + { | ||
268 | + $cache = $this->_getCacheDriver(); | ||
269 | + | ||
270 | + $cache->setNamespace('ns1'); | ||
271 | + $this->assertFalse($cache->contains('key1')); | ||
272 | + $cache->save('key1', 'test'); | ||
273 | + $this->assertTrue($cache->contains('key1')); | ||
274 | + | ||
275 | + $cache->setNamespace('ns2'); | ||
276 | + $this->assertFalse($cache->contains('key1')); | ||
277 | + $cache->save('key1', 'test'); | ||
278 | + $this->assertTrue($cache->contains('key1')); | ||
279 | + | ||
280 | + $cache->setNamespace('ns1'); | ||
281 | + $this->assertTrue($cache->contains('key1')); | ||
282 | + $cache->deleteAll(); | ||
283 | + $this->assertFalse($cache->contains('key1')); | ||
284 | + | ||
285 | + $cache->setNamespace('ns2'); | ||
286 | + $this->assertTrue($cache->contains('key1')); | ||
287 | + $cache->deleteAll(); | ||
288 | + $this->assertFalse($cache->contains('key1')); | ||
289 | + } | ||
290 | + | ||
291 | + /** | ||
292 | + * @group DCOM-43 | ||
293 | + */ | ||
294 | + public function testGetStats() | ||
295 | + { | ||
296 | + $cache = $this->_getCacheDriver(); | ||
297 | + $stats = $cache->getStats(); | ||
298 | + | ||
299 | + $this->assertArrayHasKey(Cache::STATS_HITS, $stats); | ||
300 | + $this->assertArrayHasKey(Cache::STATS_MISSES, $stats); | ||
301 | + $this->assertArrayHasKey(Cache::STATS_UPTIME, $stats); | ||
302 | + $this->assertArrayHasKey(Cache::STATS_MEMORY_USAGE, $stats); | ||
303 | + $this->assertArrayHasKey(Cache::STATS_MEMORY_AVAILABLE, $stats); | ||
304 | + } | ||
305 | + | ||
306 | + public function testFetchMissShouldReturnFalse() | ||
307 | + { | ||
308 | + $cache = $this->_getCacheDriver(); | ||
309 | + | ||
310 | + /* Ensure that caches return boolean false instead of null on a fetch | ||
311 | + * miss to be compatible with ORM integration. | ||
312 | + */ | ||
313 | + $result = $cache->fetch('nonexistent_key'); | ||
314 | + | ||
315 | + $this->assertFalse($result); | ||
316 | + $this->assertNotNull($result); | ||
317 | + } | ||
318 | + | ||
319 | + /** | ||
320 | + * Check to see that objects are correctly serialized and unserialized by the cache | ||
321 | + * provider. | ||
322 | + */ | ||
323 | + public function testCachedObject() | ||
324 | + { | ||
325 | + $cache = $this->_getCacheDriver(); | ||
326 | + $cache->deleteAll(); | ||
327 | + $obj = new \stdClass(); | ||
328 | + $obj->foo = "bar"; | ||
329 | + $obj2 = new \stdClass(); | ||
330 | + $obj2->bar = "foo"; | ||
331 | + $obj2->obj = $obj; | ||
332 | + $obj->obj2 = $obj2; | ||
333 | + $cache->save("obj", $obj); | ||
334 | + | ||
335 | + $fetched = $cache->fetch("obj"); | ||
336 | + | ||
337 | + $this->assertInstanceOf("stdClass", $obj); | ||
338 | + $this->assertInstanceOf("stdClass", $obj->obj2); | ||
339 | + $this->assertInstanceOf("stdClass", $obj->obj2->obj); | ||
340 | + $this->assertEquals("bar", $fetched->foo); | ||
341 | + $this->assertEquals("foo", $fetched->obj2->bar); | ||
342 | + } | ||
343 | + | ||
344 | + /** | ||
345 | + * Check to see that objects fetched via fetchMultiple are properly unserialized | ||
346 | + */ | ||
347 | + public function testFetchMultipleObjects() | ||
348 | + { | ||
349 | + $cache = $this->_getCacheDriver(); | ||
350 | + $cache->deleteAll(); | ||
351 | + $obj1 = new \stdClass(); | ||
352 | + $obj1->foo = "bar"; | ||
353 | + $cache->save("obj1", $obj1); | ||
354 | + $obj2 = new \stdClass(); | ||
355 | + $obj2->bar = "baz"; | ||
356 | + $cache->save("obj2", $obj2); | ||
357 | + | ||
358 | + $fetched = $cache->fetchMultiple(array("obj1", "obj2")); | ||
359 | + $this->assertInstanceOf("stdClass", $fetched["obj1"]); | ||
360 | + $this->assertInstanceOf("stdClass", $fetched["obj2"]); | ||
361 | + $this->assertEquals("bar", $fetched["obj1"]->foo); | ||
362 | + $this->assertEquals("baz", $fetched["obj2"]->bar); | ||
363 | + } | ||
364 | + | ||
365 | + /** | ||
366 | + * Return whether multiple cache providers share the same storage. | ||
367 | + * | ||
368 | + * This is used for skipping certain tests for shared storage behavior. | ||
369 | + * | ||
370 | + * @return boolean | ||
371 | + */ | ||
372 | + protected function isSharedStorage() | ||
373 | + { | ||
374 | + return true; | ||
375 | + } | ||
376 | + | ||
377 | + /** | ||
378 | + * @return \Doctrine\Common\Cache\CacheProvider | ||
379 | + */ | ||
380 | + abstract protected function _getCacheDriver(); | ||
381 | +} |
1 | +<?php | ||
2 | + | ||
3 | +namespace Doctrine\Tests\Common\Cache; | ||
4 | + | ||
5 | +use Doctrine\Common\Cache\ApcCache; | ||
6 | +use Doctrine\Common\Cache\ArrayCache; | ||
7 | +use Doctrine\Common\Cache\ChainCache; | ||
8 | + | ||
9 | +class ChainCacheTest extends CacheTest | ||
10 | +{ | ||
11 | + protected function _getCacheDriver() | ||
12 | + { | ||
13 | + return new ChainCache(array(new ArrayCache())); | ||
14 | + } | ||
15 | + | ||
16 | + public function testGetStats() | ||
17 | + { | ||
18 | + $cache = $this->_getCacheDriver(); | ||
19 | + $stats = $cache->getStats(); | ||
20 | + | ||
21 | + $this->assertInternalType('array', $stats); | ||
22 | + } | ||
23 | + | ||
24 | + public function testOnlyFetchFirstOne() | ||
25 | + { | ||
26 | + $cache1 = new ArrayCache(); | ||
27 | + $cache2 = $this->getMockForAbstractClass('Doctrine\Common\Cache\CacheProvider'); | ||
28 | + | ||
29 | + $cache2->expects($this->never())->method('doFetch'); | ||
30 | + | ||
31 | + $chainCache = new ChainCache(array($cache1, $cache2)); | ||
32 | + $chainCache->save('id', 'bar'); | ||
33 | + | ||
34 | + $this->assertEquals('bar', $chainCache->fetch('id')); | ||
35 | + } | ||
36 | + | ||
37 | + public function testFetchPropagateToFastestCache() | ||
38 | + { | ||
39 | + $cache1 = new ArrayCache(); | ||
40 | + $cache2 = new ArrayCache(); | ||
41 | + | ||
42 | + $cache2->save('bar', 'value'); | ||
43 | + | ||
44 | + $chainCache = new ChainCache(array($cache1, $cache2)); | ||
45 | + | ||
46 | + $this->assertFalse($cache1->contains('bar')); | ||
47 | + | ||
48 | + $result = $chainCache->fetch('bar'); | ||
49 | + | ||
50 | + $this->assertEquals('value', $result); | ||
51 | + $this->assertTrue($cache2->contains('bar')); | ||
52 | + } | ||
53 | + | ||
54 | + public function testNamespaceIsPropagatedToAllProviders() | ||
55 | + { | ||
56 | + $cache1 = new ArrayCache(); | ||
57 | + $cache2 = new ArrayCache(); | ||
58 | + | ||
59 | + $chainCache = new ChainCache(array($cache1, $cache2)); | ||
60 | + $chainCache->setNamespace('bar'); | ||
61 | + | ||
62 | + $this->assertEquals('bar', $cache1->getNamespace()); | ||
63 | + $this->assertEquals('bar', $cache2->getNamespace()); | ||
64 | + } | ||
65 | + | ||
66 | + public function testDeleteToAllProviders() | ||
67 | + { | ||
68 | + $cache1 = $this->getMockForAbstractClass('Doctrine\Common\Cache\CacheProvider'); | ||
69 | + $cache2 = $this->getMockForAbstractClass('Doctrine\Common\Cache\CacheProvider'); | ||
70 | + | ||
71 | + $cache1->expects($this->once())->method('doDelete'); | ||
72 | + $cache2->expects($this->once())->method('doDelete'); | ||
73 | + | ||
74 | + $chainCache = new ChainCache(array($cache1, $cache2)); | ||
75 | + $chainCache->delete('bar'); | ||
76 | + } | ||
77 | + | ||
78 | + public function testFlushToAllProviders() | ||
79 | + { | ||
80 | + $cache1 = $this->getMockForAbstractClass('Doctrine\Common\Cache\CacheProvider'); | ||
81 | + $cache2 = $this->getMockForAbstractClass('Doctrine\Common\Cache\CacheProvider'); | ||
82 | + | ||
83 | + $cache1->expects($this->once())->method('doFlush'); | ||
84 | + $cache2->expects($this->once())->method('doFlush'); | ||
85 | + | ||
86 | + $chainCache = new ChainCache(array($cache1, $cache2)); | ||
87 | + $chainCache->flushAll(); | ||
88 | + } | ||
89 | + | ||
90 | + protected function isSharedStorage() | ||
91 | + { | ||
92 | + return false; | ||
93 | + } | ||
94 | +} |
1 | +<?php | ||
2 | + | ||
3 | +namespace Doctrine\Tests\Common\Cache; | ||
4 | + | ||
5 | +use Couchbase; | ||
6 | +use Doctrine\Common\Cache\CouchbaseCache; | ||
7 | + | ||
8 | +class CouchbaseCacheTest extends CacheTest | ||
9 | +{ | ||
10 | + private $couchbase; | ||
11 | + | ||
12 | + public function setUp() | ||
13 | + { | ||
14 | + if (extension_loaded('couchbase')) { | ||
15 | + try { | ||
16 | + $this->couchbase = new Couchbase('127.0.0.1', 'Administrator', 'password', 'default'); | ||
17 | + } catch(Exception $ex) { | ||
18 | + $this->markTestSkipped('Could not instantiate the Couchbase cache because of: ' . $ex); | ||
19 | + } | ||
20 | + } else { | ||
21 | + $this->markTestSkipped('The ' . __CLASS__ .' requires the use of the couchbase extension'); | ||
22 | + } | ||
23 | + } | ||
24 | + | ||
25 | + public function testNoExpire() | ||
26 | + { | ||
27 | + $cache = $this->_getCacheDriver(); | ||
28 | + $cache->save('noexpire', 'value', 0); | ||
29 | + sleep(1); | ||
30 | + $this->assertTrue($cache->contains('noexpire'), 'Couchbase provider should support no-expire'); | ||
31 | + } | ||
32 | + | ||
33 | + public function testLongLifetime() | ||
34 | + { | ||
35 | + $cache = $this->_getCacheDriver(); | ||
36 | + $cache->save('key', 'value', 30 * 24 * 3600 + 1); | ||
37 | + | ||
38 | + $this->assertTrue($cache->contains('key'), 'Couchbase provider should support TTL > 30 days'); | ||
39 | + } | ||
40 | + | ||
41 | + protected function _getCacheDriver() | ||
42 | + { | ||
43 | + $driver = new CouchbaseCache(); | ||
44 | + $driver->setCouchbase($this->couchbase); | ||
45 | + return $driver; | ||
46 | + } | ||
47 | +} |
1 | +<?php | ||
2 | + | ||
3 | +namespace Doctrine\Tests\Common\Cache; | ||
4 | + | ||
5 | +use Doctrine\Common\Cache\Cache; | ||
6 | + | ||
7 | +/** | ||
8 | + * @group DCOM-101 | ||
9 | + */ | ||
10 | +class FileCacheTest extends \Doctrine\Tests\DoctrineTestCase | ||
11 | +{ | ||
12 | + /** | ||
13 | + * @var \Doctrine\Common\Cache\FileCache | ||
14 | + */ | ||
15 | + private $driver; | ||
16 | + | ||
17 | + protected function setUp() | ||
18 | + { | ||
19 | + $this->driver = $this->getMock( | ||
20 | + 'Doctrine\Common\Cache\FileCache', | ||
21 | + array('doFetch', 'doContains', 'doSave'), | ||
22 | + array(), '', false | ||
23 | + ); | ||
24 | + } | ||
25 | + | ||
26 | + public function getProviderFileName() | ||
27 | + { | ||
28 | + return array( | ||
29 | + //The characters :\/<>"*?| are not valid in Windows filenames. | ||
30 | + array('key:1', 'key-1'), | ||
31 | + array('key\2', 'key-2'), | ||
32 | + array('key/3', 'key-3'), | ||
33 | + array('key<4', 'key-4'), | ||
34 | + array('key>5', 'key-5'), | ||
35 | + array('key"6', 'key-6'), | ||
36 | + array('key*7', 'key-7'), | ||
37 | + array('key?8', 'key-8'), | ||
38 | + array('key|9', 'key-9'), | ||
39 | + array('key[10]', 'key[10]'), | ||
40 | + array('keyä11', 'key--11'), | ||
41 | + array('../key12', '---key12'), | ||
42 | + array('key-13', 'key__13'), | ||
43 | + ); | ||
44 | + } | ||
45 | + | ||
46 | + /** | ||
47 | + * @dataProvider getProviderFileName | ||
48 | + */ | ||
49 | + public function testInvalidFilename($key, $expected) | ||
50 | + { | ||
51 | + $cache = $this->driver; | ||
52 | + $method = new \ReflectionMethod($cache, 'getFilename'); | ||
53 | + | ||
54 | + $method->setAccessible(true); | ||
55 | + | ||
56 | + $value = $method->invoke($cache, $key); | ||
57 | + $actual = pathinfo($value, PATHINFO_FILENAME); | ||
58 | + | ||
59 | + $this->assertEquals($expected, $actual); | ||
60 | + } | ||
61 | + | ||
62 | + public function testFilenameCollision() | ||
63 | + { | ||
64 | + $data = array( | ||
65 | + 'key:0' => 'key-0', | ||
66 | + 'key\0' => 'key-0', | ||
67 | + 'key/0' => 'key-0', | ||
68 | + 'key<0' => 'key-0', | ||
69 | + 'key>0' => 'key-0', | ||
70 | + 'key"0' => 'key-0', | ||
71 | + 'key*0' => 'key-0', | ||
72 | + 'key?0' => 'key-0', | ||
73 | + 'key|0' => 'key-0', | ||
74 | + 'key-0' => 'key__0', | ||
75 | + 'keyä0' => 'key--0', | ||
76 | + ); | ||
77 | + | ||
78 | + $paths = array(); | ||
79 | + $cache = $this->driver; | ||
80 | + $method = new \ReflectionMethod($cache, 'getFilename'); | ||
81 | + | ||
82 | + $method->setAccessible(true); | ||
83 | + | ||
84 | + foreach ($data as $key => $expected) { | ||
85 | + $path = $method->invoke($cache, $key); | ||
86 | + $actual = pathinfo($path, PATHINFO_FILENAME); | ||
87 | + | ||
88 | + $this->assertNotContains($path, $paths); | ||
89 | + $this->assertEquals($expected, $actual); | ||
90 | + | ||
91 | + $paths[] = $path; | ||
92 | + } | ||
93 | + } | ||
94 | + | ||
95 | + public function testFilenameShouldCreateThePathWithFourSubDirectories() | ||
96 | + { | ||
97 | + $cache = $this->driver; | ||
98 | + $method = new \ReflectionMethod($cache, 'getFilename'); | ||
99 | + $key = 'item-key'; | ||
100 | + $expectedDir = array( | ||
101 | + '84', 'e0', 'e2', 'e8', '93', 'fe', 'bb', '73', '7a', '0f', 'ee', | ||
102 | + '0c', '89', 'd5', '3f', '4b', 'b7', 'fc', 'b4', '4c', '57', 'cd', | ||
103 | + 'f3', 'd3', '2c', 'e7', '36', '3f', '5d', '59', '77', '60' | ||
104 | + ); | ||
105 | + $expectedDir = implode(DIRECTORY_SEPARATOR, $expectedDir); | ||
106 | + | ||
107 | + $method->setAccessible(true); | ||
108 | + | ||
109 | + $path = $method->invoke($cache, $key); | ||
110 | + $filename = pathinfo($path, PATHINFO_FILENAME); | ||
111 | + $dirname = pathinfo($path, PATHINFO_DIRNAME); | ||
112 | + | ||
113 | + $this->assertEquals('item__key', $filename); | ||
114 | + $this->assertEquals(DIRECTORY_SEPARATOR . $expectedDir, $dirname); | ||
115 | + $this->assertEquals(DIRECTORY_SEPARATOR . $expectedDir . DIRECTORY_SEPARATOR . 'item__key', $path); | ||
116 | + } | ||
117 | + | ||
118 | + public function testFileExtensionCorrectlyEscaped() | ||
119 | + { | ||
120 | + $driver1 = $this->getMock( | ||
121 | + 'Doctrine\Common\Cache\FileCache', | ||
122 | + array('doFetch', 'doContains', 'doSave'), | ||
123 | + array(__DIR__, '.*') | ||
124 | + ); | ||
125 | + $driver2 = $this->getMock( | ||
126 | + 'Doctrine\Common\Cache\FileCache', | ||
127 | + array('doFetch', 'doContains', 'doSave'), | ||
128 | + array(__DIR__, '.php') | ||
129 | + ); | ||
130 | + | ||
131 | + $doGetStats = new \ReflectionMethod($driver1, 'doGetStats'); | ||
132 | + | ||
133 | + $doGetStats->setAccessible(true); | ||
134 | + | ||
135 | + $stats1 = $doGetStats->invoke($driver1); | ||
136 | + $stats2 = $doGetStats->invoke($driver2); | ||
137 | + | ||
138 | + $this->assertSame(0, $stats1[Cache::STATS_MEMORY_USAGE]); | ||
139 | + $this->assertGreaterThan(0, $stats2[Cache::STATS_MEMORY_USAGE]); | ||
140 | + } | ||
141 | + | ||
142 | + /** | ||
143 | + * @group DCOM-266 | ||
144 | + */ | ||
145 | + public function testFileExtensionSlashCorrectlyEscaped() | ||
146 | + { | ||
147 | + $driver = $this->getMock( | ||
148 | + 'Doctrine\Common\Cache\FileCache', | ||
149 | + array('doFetch', 'doContains', 'doSave'), | ||
150 | + array(__DIR__ . '/../', DIRECTORY_SEPARATOR . basename(__FILE__)) | ||
151 | + ); | ||
152 | + | ||
153 | + $doGetStats = new \ReflectionMethod($driver, 'doGetStats'); | ||
154 | + | ||
155 | + $doGetStats->setAccessible(true); | ||
156 | + | ||
157 | + $stats = $doGetStats->invoke($driver); | ||
158 | + | ||
159 | + $this->assertGreaterThan(0, $stats[Cache::STATS_MEMORY_USAGE]); | ||
160 | + } | ||
161 | +} |
1 | +<?php | ||
2 | + | ||
3 | +namespace Doctrine\Tests\Common\Cache; | ||
4 | + | ||
5 | +use Doctrine\Common\Cache\Cache; | ||
6 | +use Doctrine\Common\Cache\FilesystemCache; | ||
7 | + | ||
8 | +/** | ||
9 | + * @group DCOM-101 | ||
10 | + */ | ||
11 | +class FilesystemCacheTest extends BaseFileCacheTest | ||
12 | +{ | ||
13 | + public function testLifetime() | ||
14 | + { | ||
15 | + $cache = $this->_getCacheDriver(); | ||
16 | + | ||
17 | + // Test save | ||
18 | + $cache->save('test_key', 'testing this out', 10); | ||
19 | + | ||
20 | + // Test contains to test that save() worked | ||
21 | + $this->assertTrue($cache->contains('test_key')); | ||
22 | + | ||
23 | + // Test fetch | ||
24 | + $this->assertEquals('testing this out', $cache->fetch('test_key')); | ||
25 | + | ||
26 | + // access private methods | ||
27 | + $getFilename = new \ReflectionMethod($cache, 'getFilename'); | ||
28 | + $getNamespacedId = new \ReflectionMethod($cache, 'getNamespacedId'); | ||
29 | + | ||
30 | + $getFilename->setAccessible(true); | ||
31 | + $getNamespacedId->setAccessible(true); | ||
32 | + | ||
33 | + $id = $getNamespacedId->invoke($cache, 'test_key'); | ||
34 | + $filename = $getFilename->invoke($cache, $id); | ||
35 | + | ||
36 | + $data = ''; | ||
37 | + $lifetime = 0; | ||
38 | + $resource = fopen($filename, "r"); | ||
39 | + | ||
40 | + if (false !== ($line = fgets($resource))) { | ||
41 | + $lifetime = (integer) $line; | ||
42 | + } | ||
43 | + | ||
44 | + while (false !== ($line = fgets($resource))) { | ||
45 | + $data .= $line; | ||
46 | + } | ||
47 | + | ||
48 | + $this->assertNotEquals(0, $lifetime, 'previous lifetime could not be loaded'); | ||
49 | + | ||
50 | + // update lifetime | ||
51 | + $lifetime = $lifetime - 20; | ||
52 | + file_put_contents($filename, $lifetime . PHP_EOL . $data); | ||
53 | + | ||
54 | + // test expired data | ||
55 | + $this->assertFalse($cache->contains('test_key')); | ||
56 | + $this->assertFalse($cache->fetch('test_key')); | ||
57 | + } | ||
58 | + | ||
59 | + public function testGetStats() | ||
60 | + { | ||
61 | + $cache = $this->_getCacheDriver(); | ||
62 | + $stats = $cache->getStats(); | ||
63 | + | ||
64 | + $this->assertNull($stats[Cache::STATS_HITS]); | ||
65 | + $this->assertNull($stats[Cache::STATS_MISSES]); | ||
66 | + $this->assertNull($stats[Cache::STATS_UPTIME]); | ||
67 | + $this->assertEquals(0, $stats[Cache::STATS_MEMORY_USAGE]); | ||
68 | + $this->assertGreaterThan(0, $stats[Cache::STATS_MEMORY_AVAILABLE]); | ||
69 | + } | ||
70 | + | ||
71 | + public function testCacheInSharedDirectoryIsPerExtension() | ||
72 | + { | ||
73 | + $cache1 = new FilesystemCache($this->directory, '.foo'); | ||
74 | + $cache2 = new FilesystemCache($this->directory, '.bar'); | ||
75 | + | ||
76 | + $this->assertTrue($cache1->save('key1', 11)); | ||
77 | + $this->assertTrue($cache1->save('key2', 12)); | ||
78 | + | ||
79 | + $this->assertTrue($cache2->save('key1', 21)); | ||
80 | + $this->assertTrue($cache2->save('key2', 22)); | ||
81 | + | ||
82 | + $this->assertSame(11, $cache1->fetch('key1'), 'Cache value must not be influenced by a different cache in the same directory but different extension'); | ||
83 | + $this->assertSame(12, $cache1->fetch('key2')); | ||
84 | + $this->assertTrue($cache1->flushAll()); | ||
85 | + $this->assertFalse($cache1->fetch('key1'), 'flushAll() must delete all items with the current extension'); | ||
86 | + $this->assertFalse($cache1->fetch('key2')); | ||
87 | + | ||
88 | + $this->assertSame(21, $cache2->fetch('key1'), 'flushAll() must not remove items with a different extension in a shared directory'); | ||
89 | + $this->assertSame(22, $cache2->fetch('key2')); | ||
90 | + } | ||
91 | + | ||
92 | + public function testFlushAllWithNoExtension() | ||
93 | + { | ||
94 | + $cache = new FilesystemCache($this->directory, ''); | ||
95 | + | ||
96 | + $this->assertTrue($cache->save('key1', 1)); | ||
97 | + $this->assertTrue($cache->save('key2', 2)); | ||
98 | + $this->assertTrue($cache->flushAll()); | ||
99 | + $this->assertFalse($cache->contains('key1')); | ||
100 | + $this->assertFalse($cache->contains('key2')); | ||
101 | + } | ||
102 | + | ||
103 | + protected function _getCacheDriver() | ||
104 | + { | ||
105 | + return new FilesystemCache($this->directory); | ||
106 | + } | ||
107 | +} |
1 | +<?php | ||
2 | + | ||
3 | +namespace Doctrine\Tests\Common\Cache; | ||
4 | + | ||
5 | +use Doctrine\Common\Cache\MemcacheCache; | ||
6 | +use Memcache; | ||
7 | + | ||
8 | +class MemcacheCacheTest extends CacheTest | ||
9 | +{ | ||
10 | + private $memcache; | ||
11 | + | ||
12 | + public function setUp() | ||
13 | + { | ||
14 | + if ( ! extension_loaded('memcache')) { | ||
15 | + $this->markTestSkipped('The ' . __CLASS__ .' requires the use of memcache'); | ||
16 | + } | ||
17 | + | ||
18 | + $this->memcache = new Memcache(); | ||
19 | + | ||
20 | + if (@$this->memcache->connect('localhost', 11211) === false) { | ||
21 | + unset($this->memcache); | ||
22 | + $this->markTestSkipped('The ' . __CLASS__ .' cannot connect to memcache'); | ||
23 | + } | ||
24 | + } | ||
25 | + | ||
26 | + public function tearDown() | ||
27 | + { | ||
28 | + if ($this->memcache instanceof Memcache) { | ||
29 | + $this->memcache->flush(); | ||
30 | + } | ||
31 | + } | ||
32 | + | ||
33 | + public function testNoExpire() | ||
34 | + { | ||
35 | + $cache = $this->_getCacheDriver(); | ||
36 | + $cache->save('noexpire', 'value', 0); | ||
37 | + sleep(1); | ||
38 | + $this->assertTrue($cache->contains('noexpire'), 'Memcache provider should support no-expire'); | ||
39 | + } | ||
40 | + | ||
41 | + public function testLongLifetime() | ||
42 | + { | ||
43 | + $cache = $this->_getCacheDriver(); | ||
44 | + $cache->save('key', 'value', 30 * 24 * 3600 + 1); | ||
45 | + $this->assertTrue($cache->contains('key'), 'Memcache provider should support TTL > 30 days'); | ||
46 | + } | ||
47 | + | ||
48 | + protected function _getCacheDriver() | ||
49 | + { | ||
50 | + $driver = new MemcacheCache(); | ||
51 | + $driver->setMemcache($this->memcache); | ||
52 | + return $driver; | ||
53 | + } | ||
54 | +} |
-
请 注册 或 登录 后发表评论