diff --git a/composer.json b/composer.json index 103baca813b..d0f72dce0aa 100644 --- a/composer.json +++ b/composer.json @@ -73,6 +73,7 @@ "ext-ctype": "*", "lib-pcre": "*", "yiisoft/yii2-composer": "~2.0.4", + "psr/simple-cache": "~1.0.0", "ezyang/htmlpurifier": "~4.6", "cebe/markdown": "~1.0.0 | ~1.1.0", "bower-asset/jquery": "2.2.*@stable | 2.1.*@stable | 1.11.*@stable | 1.12.*@stable", diff --git a/composer.lock b/composer.lock index fb2c6a1460f..6d98a6b25ca 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "1e1c5caae60d6d8d5b4a3d28d9667f31", + "hash": "81cb8a6aa01acac345059695e795fd68", + "content-hash": "b36161ae5a97ecec89951d7fd5b2aa6a", "packages": [ { "name": "bower-asset/inputmask", @@ -33,18 +34,30 @@ "version": "2.2.4", "source": { "type": "git", - "url": "https://github.com/jquery/jquery-dist.git", - "reference": "c0185ab7c75aab88762c5aae780b9d83b80eda72" + "url": "https://github.com/components/jquery.git", + "reference": "981036fcb56668433a7eb0d1e71190324b4574df" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jquery/jquery-dist/zipball/c0185ab7c75aab88762c5aae780b9d83b80eda72", - "reference": "c0185ab7c75aab88762c5aae780b9d83b80eda72", - "shasum": null + "url": "https://api.github.com/repos/components/jquery/zipball/981036fcb56668433a7eb0d1e71190324b4574df", + "reference": "981036fcb56668433a7eb0d1e71190324b4574df", + "shasum": "" + }, + "type": "bower-asset-library", + "extra": { + "bower-asset-main": "dist/jquery.js", + "bower-asset-ignore": [ + "package.json" + ] }, - "type": "bower-asset", "license": [ "MIT" + ], + "keywords": [ + "browser", + "javascript", + "jquery", + "library" ] }, { @@ -59,9 +72,21 @@ "type": "zip", "url": "https://api.github.com/repos/bestiejs/punycode.js/zipball/38c8d3131a82567bfef18da09f7f4db68c84f8a3", "reference": "38c8d3131a82567bfef18da09f7f4db68c84f8a3", - "shasum": null + "shasum": "" }, - "type": "bower-asset" + "type": "bower-asset-library", + "extra": { + "bower-asset-main": "punycode.js", + "bower-asset-ignore": [ + "coverage", + "tests", + ".*", + "component.json", + "Gruntfile.js", + "node_modules", + "package.json" + ] + } }, { "name": "bower-asset/yii2-pjax", @@ -75,12 +100,24 @@ "type": "zip", "url": "https://api.github.com/repos/yiisoft/jquery-pjax/zipball/60728da6ade5879e807a49ce59ef9a72039b8978", "reference": "60728da6ade5879e807a49ce59ef9a72039b8978", - "shasum": null + "shasum": "" }, "require": { "bower-asset/jquery": ">=1.8" }, - "type": "bower-asset", + "type": "bower-asset-library", + "extra": { + "bower-asset-main": "./jquery.pjax.js", + "bower-asset-ignore": [ + ".travis.yml", + "Gemfile", + "Gemfile.lock", + "CONTRIBUTING.md", + "vendor/", + "script/", + "test/" + ] + }, "license": [ "MIT" ] @@ -143,7 +180,7 @@ "markdown", "markdown-extra" ], - "time": "2017-07-16T21:13:23+00:00" + "time": "2017-07-16 21:13:23" }, { "name": "ezyang/htmlpurifier", @@ -190,7 +227,55 @@ "keywords": [ "html" ], - "time": "2017-06-03T02:28:16+00:00" + "time": "2017-06-03 02:28:16" + }, + { + "name": "psr/simple-cache", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "753fa598e8f3b9966c886fe13f370baa45ef0e24" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/753fa598e8f3b9966c886fe13f370baa45ef0e24", + "reference": "753fa598e8f3b9966c886fe13f370baa45ef0e24", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "time": "2017-01-02 13:31:39" }, { "name": "yiisoft/yii2-composer", @@ -240,7 +325,7 @@ "extension installer", "yii2" ], - "time": "2016-12-20T13:26:02+00:00" + "time": "2016-12-20 13:26:02" } ], "packages-dev": [ @@ -275,25 +360,25 @@ } ], "description": "a small tool to convert text file indentation", - "time": "2014-05-23T14:40:08+00:00" + "time": "2014-05-23 14:40:08" }, { "name": "doctrine/annotations", - "version": "v1.4.0", + "version": "v1.5.0", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", - "reference": "54cacc9b81758b14e3ce750f205a393d52339e97" + "reference": "5beebb01b025c94e93686b7a0ed3edae81fe3e7f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/54cacc9b81758b14e3ce750f205a393d52339e97", - "reference": "54cacc9b81758b14e3ce750f205a393d52339e97", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/5beebb01b025c94e93686b7a0ed3edae81fe3e7f", + "reference": "5beebb01b025c94e93686b7a0ed3edae81fe3e7f", "shasum": "" }, "require": { "doctrine/lexer": "1.*", - "php": "^5.6 || ^7.0" + "php": "^7.1" }, "require-dev": { "doctrine/cache": "1.*", @@ -302,7 +387,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4.x-dev" + "dev-master": "1.5.x-dev" } }, "autoload": { @@ -343,36 +428,36 @@ "docblock", "parser" ], - "time": "2017-02-24T16:22:25+00:00" + "time": "2017-07-22 10:58:02" }, { "name": "doctrine/instantiator", - "version": "1.0.5", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", + "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", "shasum": "" }, "require": { - "php": ">=5.3,<8.0-DEV" + "php": "^7.1" }, "require-dev": { "athletic/athletic": "~0.1.8", "ext-pdo": "*", "ext-phar": "*", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.0" + "phpunit/phpunit": "^6.2.3", + "squizlabs/php_codesniffer": "^3.0.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.2.x-dev" } }, "autoload": { @@ -397,7 +482,7 @@ "constructor", "instantiate" ], - "time": "2015-06-14T21:17:01+00:00" + "time": "2017-07-22 11:58:36" }, { "name": "doctrine/lexer", @@ -451,7 +536,7 @@ "lexer", "parser" ], - "time": "2014-09-09T13:34:57+00:00" + "time": "2014-09-09 13:34:57" }, { "name": "friendsofphp/php-cs-fixer", @@ -535,7 +620,7 @@ } ], "description": "A tool to automatically fix PHP code style", - "time": "2017-07-18T15:16:38+00:00" + "time": "2017-07-18 15:16:38" }, { "name": "gecko-packages/gecko-php-unit", @@ -574,7 +659,7 @@ "filesystem", "phpunit" ], - "time": "2017-06-20T11:22:48+00:00" + "time": "2017-06-20 11:22:48" }, { "name": "ircmaxell/password-compat", @@ -616,7 +701,7 @@ "hashing", "password" ], - "time": "2014-11-20T16:49:30+00:00" + "time": "2014-11-20 16:49:30" }, { "name": "myclabs/deep-copy", @@ -658,7 +743,7 @@ "object", "object graph" ], - "time": "2017-04-12T18:52:22+00:00" + "time": "2017-04-12 18:52:22" }, { "name": "paragonie/random_compat", @@ -706,7 +791,7 @@ "pseudorandom", "random" ], - "time": "2017-03-13T16:27:32+00:00" + "time": "2017-03-13 16:27:32" }, { "name": "phar-io/manifest", @@ -761,7 +846,7 @@ } ], "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "time": "2017-03-05T18:14:27+00:00" + "time": "2017-03-05 18:14:27" }, { "name": "phar-io/version", @@ -808,7 +893,7 @@ } ], "description": "Library for handling version information and constraints", - "time": "2017-03-05T17:38:23+00:00" + "time": "2017-03-05 17:38:23" }, { "name": "phpdocumentor/reflection-common", @@ -862,26 +947,26 @@ "reflection", "static analysis" ], - "time": "2015-12-27T11:43:31+00:00" + "time": "2015-12-27 11:43:31" }, { "name": "phpdocumentor/reflection-docblock", - "version": "3.2.0", + "version": "3.2.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "46f7e8bb075036c92695b15a1ddb6971c751e585" + "reference": "4aada1f93c72c35e22fb1383b47fee43b8f1d157" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/46f7e8bb075036c92695b15a1ddb6971c751e585", - "reference": "46f7e8bb075036c92695b15a1ddb6971c751e585", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/4aada1f93c72c35e22fb1383b47fee43b8f1d157", + "reference": "4aada1f93c72c35e22fb1383b47fee43b8f1d157", "shasum": "" }, "require": { "php": ">=5.5", "phpdocumentor/reflection-common": "^1.0@dev", - "phpdocumentor/type-resolver": "^0.4.0", + "phpdocumentor/type-resolver": "^0.3.0", "webmozart/assert": "^1.0" }, "require-dev": { @@ -907,20 +992,20 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2017-07-15T11:38:20+00:00" + "time": "2017-08-08 06:39:58" }, { "name": "phpdocumentor/type-resolver", - "version": "0.4.0", + "version": "0.3.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" + "reference": "fb3933512008d8162b3cdf9e18dba9309b7c3773" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/fb3933512008d8162b3cdf9e18dba9309b7c3773", + "reference": "fb3933512008d8162b3cdf9e18dba9309b7c3773", "shasum": "" }, "require": { @@ -954,7 +1039,7 @@ "email": "me@mikevanriel.com" } ], - "time": "2017-07-14T14:27:02+00:00" + "time": "2017-06-03 08:32:36" }, { "name": "phpspec/prophecy", @@ -1017,32 +1102,32 @@ "spy", "stub" ], - "time": "2017-03-02T20:05:34+00:00" + "time": "2017-03-02 20:05:34" }, { "name": "phpunit/php-code-coverage", - "version": "5.2.1", + "version": "5.2.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "dc421f9ca5082a0c0cb04afb171c765f79add85b" + "reference": "8ed1902a57849e117b5651fc1a5c48110946c06b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/dc421f9ca5082a0c0cb04afb171c765f79add85b", - "reference": "dc421f9ca5082a0c0cb04afb171c765f79add85b", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/8ed1902a57849e117b5651fc1a5c48110946c06b", + "reference": "8ed1902a57849e117b5651fc1a5c48110946c06b", "shasum": "" }, "require": { "ext-dom": "*", "ext-xmlwriter": "*", "php": "^7.0", - "phpunit/php-file-iterator": "^1.3", - "phpunit/php-text-template": "^1.2", + "phpunit/php-file-iterator": "^1.4.2", + "phpunit/php-text-template": "^1.2.1", "phpunit/php-token-stream": "^1.4.11 || ^2.0", - "sebastian/code-unit-reverse-lookup": "^1.0", + "sebastian/code-unit-reverse-lookup": "^1.0.1", "sebastian/environment": "^3.0", - "sebastian/version": "^2.0", + "sebastian/version": "^2.0.1", "theseer/tokenizer": "^1.1" }, "require-dev": { @@ -1050,7 +1135,7 @@ "phpunit/phpunit": "^6.0" }, "suggest": { - "ext-xdebug": "^2.5.3" + "ext-xdebug": "^2.5.5" }, "type": "library", "extra": { @@ -1081,7 +1166,7 @@ "testing", "xunit" ], - "time": "2017-04-21T08:03:57+00:00" + "time": "2017-08-03 12:40:43" }, { "name": "phpunit/php-file-iterator", @@ -1128,7 +1213,7 @@ "filesystem", "iterator" ], - "time": "2016-10-03T07:40:28+00:00" + "time": "2016-10-03 07:40:28" }, { "name": "phpunit/php-text-template", @@ -1169,7 +1254,7 @@ "keywords": [ "template" ], - "time": "2015-06-21T13:50:34+00:00" + "time": "2015-06-21 13:50:34" }, { "name": "phpunit/php-timer", @@ -1218,33 +1303,33 @@ "keywords": [ "timer" ], - "time": "2017-02-26T11:10:40+00:00" + "time": "2017-02-26 11:10:40" }, { "name": "phpunit/php-token-stream", - "version": "1.4.11", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7" + "reference": "ecb0b2cdaa0add708fe6f329ef65ae0c5225130b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e03f8f67534427a787e21a385a67ec3ca6978ea7", - "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/ecb0b2cdaa0add708fe6f329ef65ae0c5225130b", + "reference": "ecb0b2cdaa0add708fe6f329ef65ae0c5225130b", "shasum": "" }, "require": { "ext-tokenizer": "*", - "php": ">=5.3.3" + "php": "^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.2" + "phpunit/phpunit": "^6.2.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -1267,20 +1352,20 @@ "keywords": [ "tokenizer" ], - "time": "2017-02-27T10:12:30+00:00" + "time": "2017-08-03 14:17:41" }, { "name": "phpunit/phpunit", - "version": "6.2.3", + "version": "6.2.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "fa5711d0559fc4b64deba0702be52d41434cbcb7" + "reference": "ff3a76a58ac293657808aefd58c8aaf05945f4d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fa5711d0559fc4b64deba0702be52d41434cbcb7", - "reference": "fa5711d0559fc4b64deba0702be52d41434cbcb7", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/ff3a76a58ac293657808aefd58c8aaf05945f4d9", + "reference": "ff3a76a58ac293657808aefd58c8aaf05945f4d9", "shasum": "" }, "require": { @@ -1300,7 +1385,7 @@ "phpunit/php-timer": "^1.0.6", "phpunit/phpunit-mock-objects": "^4.0", "sebastian/comparator": "^2.0", - "sebastian/diff": "^1.4.3 || ^2.0", + "sebastian/diff": "^1.4.3", "sebastian/environment": "^3.0.2", "sebastian/exporter": "^3.1", "sebastian/global-state": "^1.1 || ^2.0", @@ -1351,26 +1436,26 @@ "testing", "xunit" ], - "time": "2017-07-03T15:54:24+00:00" + "time": "2017-08-03 13:59:28" }, { "name": "phpunit/phpunit-mock-objects", - "version": "4.0.2", + "version": "4.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "d8833b396dce9162bb2eb5d59aee5a3ab3cfa5b4" + "reference": "2f789b59ab89669015ad984afa350c4ec577ade0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/d8833b396dce9162bb2eb5d59aee5a3ab3cfa5b4", - "reference": "d8833b396dce9162bb2eb5d59aee5a3ab3cfa5b4", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/2f789b59ab89669015ad984afa350c4ec577ade0", + "reference": "2f789b59ab89669015ad984afa350c4ec577ade0", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.0.2", + "doctrine/instantiator": "^1.0.5", "php": "^7.0", - "phpunit/php-text-template": "^1.2", + "phpunit/php-text-template": "^1.2.1", "sebastian/exporter": "^3.0" }, "conflict": { @@ -1410,7 +1495,7 @@ "mock", "xunit" ], - "time": "2017-06-30T08:15:21+00:00" + "time": "2017-08-03 14:08:16" }, { "name": "psr/log", @@ -1457,7 +1542,7 @@ "psr", "psr-3" ], - "time": "2016-10-10T12:19:37+00:00" + "time": "2016-10-10 12:19:37" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -1502,7 +1587,7 @@ ], "description": "Looks up which function or method a line of code belongs to", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "time": "2017-03-04T06:30:41+00:00" + "time": "2017-03-04 06:30:41" }, { "name": "sebastian/comparator", @@ -1566,7 +1651,7 @@ "compare", "equality" ], - "time": "2017-03-03T06:26:08+00:00" + "time": "2017-03-03 06:26:08" }, { "name": "sebastian/diff", @@ -1618,7 +1703,7 @@ "keywords": [ "diff" ], - "time": "2017-05-22T07:24:03+00:00" + "time": "2017-05-22 07:24:03" }, { "name": "sebastian/environment", @@ -1668,7 +1753,7 @@ "environment", "hhvm" ], - "time": "2017-07-01T08:51:00+00:00" + "time": "2017-07-01 08:51:00" }, { "name": "sebastian/exporter", @@ -1735,7 +1820,7 @@ "export", "exporter" ], - "time": "2017-04-03T13:19:02+00:00" + "time": "2017-04-03 13:19:02" }, { "name": "sebastian/global-state", @@ -1786,25 +1871,25 @@ "keywords": [ "global state" ], - "time": "2017-04-27T15:39:26+00:00" + "time": "2017-04-27 15:39:26" }, { "name": "sebastian/object-enumerator", - "version": "3.0.2", + "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "31dd3379d16446c5d86dec32ab1ad1f378581ad8" + "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/31dd3379d16446c5d86dec32ab1ad1f378581ad8", - "reference": "31dd3379d16446c5d86dec32ab1ad1f378581ad8", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", "shasum": "" }, "require": { "php": "^7.0", - "sebastian/object-reflector": "^1.0", + "sebastian/object-reflector": "^1.1.1", "sebastian/recursion-context": "^3.0" }, "require-dev": { @@ -1833,7 +1918,7 @@ ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2017-03-12T15:17:29+00:00" + "time": "2017-08-03 12:35:26" }, { "name": "sebastian/object-reflector", @@ -1878,7 +1963,7 @@ ], "description": "Allows reflection of object attributes, including inherited and non-public ones", "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "time": "2017-03-29T09:07:27+00:00" + "time": "2017-03-29 09:07:27" }, { "name": "sebastian/recursion-context", @@ -1931,7 +2016,7 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2017-03-03T06:23:57+00:00" + "time": "2017-03-03 06:23:57" }, { "name": "sebastian/resource-operations", @@ -1973,7 +2058,7 @@ ], "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "time": "2015-07-28T20:34:47+00:00" + "time": "2015-07-28 20:34:47" }, { "name": "sebastian/version", @@ -2016,20 +2101,20 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2016-10-03T07:35:21+00:00" + "time": "2016-10-03 07:35:21" }, { "name": "symfony/console", - "version": "v3.3.5", + "version": "v3.3.6", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "a97e45d98c59510f085fa05225a1acb74dfe0546" + "reference": "b0878233cb5c4391347e5495089c7af11b8e6201" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/a97e45d98c59510f085fa05225a1acb74dfe0546", - "reference": "a97e45d98c59510f085fa05225a1acb74dfe0546", + "url": "https://api.github.com/repos/symfony/console/zipball/b0878233cb5c4391347e5495089c7af11b8e6201", + "reference": "b0878233cb5c4391347e5495089c7af11b8e6201", "shasum": "" }, "require": { @@ -2085,20 +2170,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2017-07-03T13:19:36+00:00" + "time": "2017-07-29 21:27:59" }, { "name": "symfony/debug", - "version": "v3.3.5", + "version": "v3.3.6", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "63b85a968486d95ff9542228dc2e4247f16f9743" + "reference": "7c13ae8ce1e2adbbd574fc39de7be498e1284e13" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/63b85a968486d95ff9542228dc2e4247f16f9743", - "reference": "63b85a968486d95ff9542228dc2e4247f16f9743", + "url": "https://api.github.com/repos/symfony/debug/zipball/7c13ae8ce1e2adbbd574fc39de7be498e1284e13", + "reference": "7c13ae8ce1e2adbbd574fc39de7be498e1284e13", "shasum": "" }, "require": { @@ -2141,11 +2226,11 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2017-07-05T13:02:37+00:00" + "time": "2017-07-28 15:27:31" }, { "name": "symfony/event-dispatcher", - "version": "v3.3.5", + "version": "v3.3.6", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", @@ -2204,11 +2289,11 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2017-06-09T14:53:08+00:00" + "time": "2017-06-09 14:53:08" }, { "name": "symfony/filesystem", - "version": "v3.3.5", + "version": "v3.3.6", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", @@ -2253,11 +2338,11 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2017-07-11T07:17:58+00:00" + "time": "2017-07-11 07:17:58" }, { "name": "symfony/finder", - "version": "v3.3.5", + "version": "v3.3.6", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", @@ -2302,11 +2387,11 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2017-06-01T21:01:25+00:00" + "time": "2017-06-01 21:01:25" }, { "name": "symfony/options-resolver", - "version": "v3.3.5", + "version": "v3.3.6", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", @@ -2356,7 +2441,7 @@ "configuration", "options" ], - "time": "2017-04-12T14:14:56+00:00" + "time": "2017-04-12 14:14:56" }, { "name": "symfony/polyfill-mbstring", @@ -2415,7 +2500,7 @@ "portable", "shim" ], - "time": "2017-06-09T14:24:12+00:00" + "time": "2017-06-09 14:24:12" }, { "name": "symfony/polyfill-php54", @@ -2473,7 +2558,7 @@ "portable", "shim" ], - "time": "2017-06-09T08:25:21+00:00" + "time": "2017-06-09 08:25:21" }, { "name": "symfony/polyfill-php55", @@ -2529,7 +2614,7 @@ "portable", "shim" ], - "time": "2017-06-09T08:25:21+00:00" + "time": "2017-06-09 08:25:21" }, { "name": "symfony/polyfill-php70", @@ -2588,7 +2673,7 @@ "portable", "shim" ], - "time": "2017-06-09T14:24:12+00:00" + "time": "2017-06-09 14:24:12" }, { "name": "symfony/polyfill-php72", @@ -2643,11 +2728,11 @@ "portable", "shim" ], - "time": "2017-06-09T08:25:21+00:00" + "time": "2017-06-09 08:25:21" }, { "name": "symfony/process", - "version": "v3.3.5", + "version": "v3.3.6", "source": { "type": "git", "url": "https://github.com/symfony/process.git", @@ -2692,11 +2777,11 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2017-07-13T13:05:09+00:00" + "time": "2017-07-13 13:05:09" }, { "name": "symfony/stopwatch", - "version": "v3.3.5", + "version": "v3.3.6", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", @@ -2741,7 +2826,7 @@ ], "description": "Symfony Stopwatch Component", "homepage": "https://symfony.com", - "time": "2017-04-12T14:14:56+00:00" + "time": "2017-04-12 14:14:56" }, { "name": "theseer/tokenizer", @@ -2781,7 +2866,7 @@ } ], "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "time": "2017-04-07T12:08:54+00:00" + "time": "2017-04-07 12:08:54" }, { "name": "webmozart/assert", @@ -2831,7 +2916,7 @@ "check", "validate" ], - "time": "2016-11-23T20:04:58+00:00" + "time": "2016-11-23 20:04:58" } ], "aliases": [], diff --git a/docs/guide/caching-data.md b/docs/guide/caching-data.md index aae0f08f49f..54d789daea6 100644 --- a/docs/guide/caching-data.md +++ b/docs/guide/caching-data.md @@ -12,7 +12,7 @@ a [cache component](#cache-components): // try retrieving $data from cache $data = $cache->get($key); -if ($data === false) { +if ($data === null) { // $data is not found in cache, calculate it from scratch $data = $this->calculateSomething(); @@ -58,22 +58,25 @@ such as memory, files, databases. Cache components are usually registered as [application components](structure-application-components.md) so that they can be globally configurable and accessible. The following code shows how to configure the `cache` application component to use -[memcached](http://memcached.org/) with two cache servers: +[memcached](http://memcached.org/) handler with two cache servers: ```php 'components' => [ 'cache' => [ - 'class' => 'yii\caching\MemCache', - 'servers' => [ - [ - 'host' => 'server1', - 'port' => 11211, - 'weight' => 100, - ], - [ - 'host' => 'server2', - 'port' => 11211, - 'weight' => 50, + 'class' => yii\caching\Cache::class, + 'handler' => [ + 'class' => yii\caching\MemCache::class, + 'servers' => [ + [ + 'host' => 'server1', + 'port' => 11211, + 'weight' => 100, + ], + [ + 'host' => 'server2', + 'port' => 11211, + 'weight' => 50, + ], ], ], ], @@ -82,7 +85,7 @@ and accessible. The following code shows how to configure the `cache` applicatio You can then access the above cache component using the expression `Yii::$app->cache`. -Because all cache components support the same set of APIs, you can swap the underlying cache component +Because all cache handlers support the same set of APIs, you can swap the underlying cache component with a different one by reconfiguring it in the application configuration without modifying the code that uses the cache. For example, you can modify the above configuration to use [[yii\caching\ApcCache|APC cache]]: @@ -90,7 +93,10 @@ For example, you can modify the above configuration to use [[yii\caching\ApcCach ```php 'components' => [ 'cache' => [ - 'class' => 'yii\caching\ApcCache', + 'class' => yii\caching\Cache::class, + 'handler' => [ + 'class' => yii\caching\ApcCache::class, + ], ], ], ``` @@ -101,7 +107,7 @@ For example, you can modify the above configuration to use [[yii\caching\ApcCach ### Supported Cache Storage -Yii supports a wide range of cache storage. The following is a summary: +Yii supports a wide range of cache handlers. The following is a summary: * [[yii\caching\ApcCache]]: uses PHP [APC](http://php.net/manual/en/book.apc.php) extension. This option can be considered as the fastest one when dealing with cache for a centralized thick application (e.g. one @@ -117,10 +123,9 @@ Yii supports a wide range of cache storage. The following is a summary: `Yii::$app->cache` might be `null`. * [[yii\caching\FileCache]]: uses standard files to store cached data. This is particularly suitable to cache large chunk of data, such as page content. -* [[yii\caching\MemCache]]: uses PHP [memcache](http://php.net/manual/en/book.memcache.php) - and [memcached](http://php.net/manual/en/book.memcached.php) extensions. This option can be considered as - the fastest one when dealing with cache in a distributed applications (e.g. with several servers, load - balancers, etc.) +* [[yii\caching\MemCached]]: uses PHP [memcached](http://php.net/manual/en/book.memcached.php) extension. + This option can be considered as the fastest one when dealing with cache in a distributed applications + (e.g. with several servers, load balancers, etc.) * [[yii\redis\Cache]]: implements a cache component based on [Redis](http://redis.io/) key-value store (redis version 2.6.12 or higher is required). * [[yii\caching\WinCache]]: uses PHP [WinCache](http://iis.net/downloads/microsoft/wincache-extension) @@ -136,27 +141,31 @@ Yii supports a wide range of cache storage. The following is a summary: All cache components have the same base class [[yii\caching\Cache]] and thus support the following APIs: -* [[yii\caching\Cache::get()|get()]]: retrieves a data item from cache with a specified key. A `false` - value will be returned if the data item is not found in the cache or is expired/invalidated. +* [[yii\caching\Cache::get()|get()]]: retrieves a data item from cache with a specified key. A `null` + value will be returned if the data item is not found in the cache or is expired/invalidated. Alternatively you can specify + default value to return by passing it as a second argument. +* [[yii\caching\Cache::getMultiple()|getMultiple()]]: retrieves multiple data items from cache with the specified keys. For each + key if the data item is not found in the cache or is expired/invalidated, `null` is returned. Alternatively you can specify + default value to return by passing it as a second argument. * [[yii\caching\Cache::set()|set()]]: stores a data item identified by a key in cache. +* [[yii\caching\Cache::setMultiple()|setMultiple()]]: stores multiple data items in cache. Each item is identified by a key. * [[yii\caching\Cache::add()|add()]]: stores a data item identified by a key in cache if the key is not found in the cache. +* [[yii\caching\Cache::addMultiple()|addMultiple()]]: stores multiple data items in cache. Each item is identified by a key. + If a key already exists in the cache, the data item will be skipped. * [[yii\caching\Cache::getOrSet()|getOrSet()]]: retrieves a data item from cache with a specified key or executes passed callback, stores return of the callback in a cache by a key and returns that data. -* [[yii\caching\Cache::multiGet()|multiGet()]]: retrieves multiple data items from cache with the specified keys. -* [[yii\caching\Cache::multiSet()|multiSet()]]: stores multiple data items in cache. Each item is identified by a key. -* [[yii\caching\Cache::multiAdd()|multiAdd()]]: stores multiple data items in cache. Each item is identified by a key. - If a key already exists in the cache, the data item will be skipped. -* [[yii\caching\Cache::exists()|exists()]]: returns a value indicating whether the specified key is found in the cache. +* [[yii\caching\Cache::has()|has()]]: returns a value indicating whether the specified key is found in the cache. * [[yii\caching\Cache::delete()|delete()]]: removes a data item identified by a key from the cache. -* [[yii\caching\Cache::flush()|flush()]]: removes all data items from the cache. +* [[yii\caching\Cache::deleteMultiple()|deleteMultiple()]]: removes multiple data items identified by array of keys from cache. +* [[yii\caching\Cache::clear()|clear()]]: removes all data items from the cache. -> Note: Do not cache a `false` boolean value directly because the [[yii\caching\Cache::get()|get()]] method uses -`false` return value to indicate the data item is not found in the cache. You may put `false` in an array and cache +> Note: Do not cache a `null` value directly because the [[yii\caching\Cache::get()|get()]] method uses +`null` return value to indicate the data item is not found in the cache. You may put `null` in an array and cache this array instead to avoid this problem. Some cache storage, such as MemCache, APC, support retrieving multiple cached values in a batch mode, -which may reduce the overhead involved in retrieving cached data. The APIs [[yii\caching\Cache::multiGet()|multiGet()]] -and [[yii\caching\Cache::multiAdd()|multiAdd()]] are provided to exploit this feature. In case the underlying cache storage +which may reduce the overhead involved in retrieving cached data. The APIs [[yii\caching\Cache::getMultiple()|getMultiple()]] +and [[yii\caching\Cache::addMultiple()|addMultiple()]] are provided to exploit this feature. In case the underlying cache storage does not support this feature, it will be simulated. Because [[yii\caching\Cache]] implements `ArrayAccess`, a cache component can be used like an array. The following @@ -191,19 +200,22 @@ For example, [[yii\db\Schema]] uses the following key to cache schema informatio As you can see, the key includes all necessary information needed to uniquely specify a database table. -> Note: Values stored in cache via [[yii\caching\Cache::multiSet()|multiSet()]] or [[yii\caching\Cache::multiAdd()|multiAdd()]] can +> Note: Values stored in cache via [[yii\caching\Cache::setMultiple()|setMultiple()]] or [[yii\caching\Cache::addMultiple()|addMultiple()]] can have only string or integer keys. If you need to set more complex key store the value separately via [[yii\caching\Cache::set()|set()]] or [[yii\caching\Cache::add()|add()]]. When the same cache storage is used by different applications, you should specify a unique cache key prefix -for each application to avoid conflicts of cache keys. This can be done by configuring the [[yii\caching\Cache::keyPrefix]] +for each application to avoid conflicts of cache keys. This can be done by configuring the [[yii\caching\SimpleCache::keyPrefix]] property. For example, in the application configuration you can write the following code: ```php 'components' => [ 'cache' => [ - 'class' => 'yii\caching\ApcCache', - 'keyPrefix' => 'myapp', // a unique cache key prefix + 'class' => 'yii\caching\Cache', + 'handler' => [ + 'class' => 'yii\caching\ApcCache', + 'keyPrefix' => 'myapp', // a unique cache key prefix + ], ], ], ``` @@ -227,14 +239,13 @@ $cache->set($key, $data, 45); sleep(50); $data = $cache->get($key); -if ($data === false) { +if ($data === null) { // $data is expired or is not found in the cache } ``` -Since 2.0.11 you may set [[yii\caching\Cache::$defaultDuration|defaultDuration]] value in your cache component configuration if you prefer a custom cache duration -over the default unlimited duration. -This will allow you not to pass custom `duration` parameter to [[yii\caching\Cache::set()|set()]] each time. +Since 2.0.11 you may set [[yii\caching\SimpleCache::$defaultTtl|defaultTtl]] value in your cache component handler configuration if you prefer a custom cache duration over the default unlimited duration. +This will allow you not to pass custom `ttl` parameter to [[yii\caching\Cache::set()|set()]] each time. ### Cache Dependencies @@ -272,9 +283,9 @@ Below is a summary of the available cache dependencies: - [[yii\caching\TagDependency]]: associates a cached data item with one or multiple tags. You may invalidate the cached data items with the specified tag(s) by calling [[yii\caching\TagDependency::invalidate()]]. -> Note: Avoid using [[yii\caching\Cache::exists()|exists()]] method along with dependencies. It does not check whether +> Note: Avoid using [[yii\caching\Cache::has()|has()]] method along with dependencies. It does not check whether the dependency associated with the cached data, if there is any, has changed. So a call to - [[yii\caching\Cache::get()|get()]] may return `false` while [[yii\caching\Cache::exists()|exists()]] returns `true`. + [[yii\caching\Cache::get()|get()]] may return `false` while [[yii\caching\Cache::has()|has()]] returns `true`. ## Query Caching @@ -309,15 +320,15 @@ $result = Customer::getDb()->cache(function ($db) { and are potentially more efficient. -### Cache Flushing +### Clearing Cache -When you need to invalidate all the stored cache data, you can call [[yii\caching\Cache::flush()]]. +When you need to invalidate all the stored cache data, you can call [[yii\caching\Cache::clear()]]. -You can flush the cache from the console by calling `yii cache/flush` as well. +You can flush the cache from the console by calling `yii cache/clear` as well. - `yii cache`: lists the available caches in application - - `yii cache/flush cache1 cache2`: flushes the cache components `cache1`, `cache2` (you can pass multiple component + - `yii cache/clear cache1 cache2`: clears the cache components `cache1`, `cache2` (you can pass multiple component names separated with space) - - `yii cache/flush-all`: flushes all cache components in the application + - `yii cache/clear-all`: clears all cache components in the application > Info: Console application uses a separate configuration file by default. Ensure, that you have the same caching components in your web and console application configs to reach the proper effect. diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index c694f3cd2ae..a47fa3b5b77 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -4,7 +4,8 @@ Yii Framework 2 Change Log 2.1.0 under development ----------------------- -- Enh #13799: CAPTCHA rendering logic extracted into `yii\captcha\DriverInterface`, which instance is available via `yii\captcha\CaptchaAction::$driver` field (vladis84, klimov-paul) +- Enh #879: Caching implementation refactored according to PSR-16 'Simple Cache' specification (klimov-paul) +- Enh #13799: CAPTCHA rendering logic extracted into `yii\captcha\DriverInterface`, which instance is available via `yii\captcha\CaptchaAction::$driver` field (vladis84, klimov-paul) - Enh #9260: Mail view rendering encapsulated into `yii\mail\Template` class allowing rendering in isolation and access to `yii\mail\MessageInterface` instance via `$this->context->message` inside the view (klimov-paul) - Enh #11058: Add `$checkAjax` parameter to method `yii\web\Controller::redirect()` which controls redirection in AJAX and PJAX requests (ivanovyordan) - Enh #12385: Methods `addHeader()`, `setHeader()`, `getHeader()`, `setHeaders()` have been added to `yii\i18n\MessageInterface` allowing setup of custom message headers (klimov-paul) diff --git a/framework/UPGRADE.md b/framework/UPGRADE.md index 27f62deb967..ba53125b768 100644 --- a/framework/UPGRADE.md +++ b/framework/UPGRADE.md @@ -73,6 +73,17 @@ Upgrade from Yii 2.0.x instance is available via `yii\captcha\CaptchaAction::$driver` field. All image settings now should be passed to the driver fields instead of action. Automatic detection of the rendering driver is no longer supported. * `yii\captcha\Captcha::checkRequirements()` method has been removed. +* All cache related classes interface has been changed according to PSR-16 "Simple Cache" specification. Make sure you + change your invocations for the cache methods accordingly. The most notable changes affects methods `get()` and `getMultiple()` + as they now accept `$default` argument, which value will be returned in case there is no value in the cache. This makes + the default return value to be `null` instead of `false`. +* Particular cache implementation should now be configured as `yii\caching\Cache::$handler` property instead of the + component itself. Properties `$defaultTtl`, `$serializer` and `$keyPrefix` has been moved to cache handler and should + be configured there. Creating your own cache implementation you should implement `\Psr\SimpleCache\CacheInterface` or + extend `yii\caching\SimpleCache` abstract class. Use `yii\caching\CacheInterface` only if you wish to replace `yii\caching\Cache` + component providing your own solution for cache dependency handling. +* Console command used to clear cache now calls related actions "clear" instead of "flush". + Upgrade from Yii 2.0.12 ----------------------- diff --git a/framework/caching/ApcCache.php b/framework/caching/ApcCache.php index b9a2d8171f6..d132e731afb 100644 --- a/framework/caching/ApcCache.php +++ b/framework/caching/ApcCache.php @@ -15,14 +15,31 @@ * To use this application component, the [APCu PHP extension](http://www.php.net/apcu) must be loaded. * In order to enable APCu for CLI you should add "apc.enable_cli = 1" to your php.ini. * - * See [[Cache]] for common cache operations that ApcCache supports. + * Application configuration example: + * + * ```php + * return [ + * 'components' => [ + * 'cache' => [ + * 'class' => yii\caching\Cache::class, + * 'handler' => [ + * 'class' => yii\caching\ApcCache::class, + * ], + * ], + * // ... + * ], + * // ... + * ]; + * ``` + * + * See [[\Psr\SimpleCache\CacheInterface]] for common cache operations that ApcCache supports. * * For more details and usage information on Cache, see the [guide article on caching](guide:caching-overview). * * @author Qiang Xue * @since 2.0 */ -class ApcCache extends Cache +class ApcCache extends SimpleCache { /** * Initializes this application component. @@ -38,27 +55,15 @@ public function init() } /** - * Checks whether a specified key exists in the cache. - * This can be faster than getting the value from the cache if the data is big. - * Note that this method does not check whether the dependency associated - * with the cached data, if there is any, has changed. So a call to [[get]] - * may return false while exists returns true. - * @param mixed $key a key identifying the cached value. This can be a simple string or - * a complex data structure consisting of factors representing the key. - * @return bool true if a value exists in cache, false if the value is not in the cache or expired. + * {@inheritdoc} */ - public function exists($key) + public function has($key) { - $key = $this->buildKey($key); - - return apcu_exists($key); + return apcu_exists($this->normalizeKey($key)); } /** - * Retrieves a value from cache with a specified key. - * This is the implementation of the method declared in the parent class. - * @param string $key a unique key identifying the cached value - * @return mixed|false the value stored in cache, false if the value is not in the cache or expired. + * {@inheritdoc} */ protected function getValue($key) { @@ -66,9 +71,7 @@ protected function getValue($key) } /** - * Retrieves multiple values from cache with the specified keys. - * @param array $keys a list of keys identifying the cached values - * @return array a list of cached values indexed by the keys + * {@inheritdoc} */ protected function getValues($keys) { @@ -77,63 +80,24 @@ protected function getValues($keys) } /** - * Stores a value identified by a key in cache. - * This is the implementation of the method declared in the parent class. - * - * @param string $key the key identifying the value to be cached - * @param mixed $value the value to be cached. Most often it's a string. If you have disabled [[serializer]], - * it could be something else. - * @param int $duration the number of seconds in which the cached value will expire. 0 means never expire. - * @return bool true if the value is successfully stored into cache, false otherwise. - */ - protected function setValue($key, $value, $duration) - { - return apcu_store($key, $value, $duration); - } - - /** - * Stores multiple key-value pairs in cache. - * @param array $data array where key corresponds to cache key while value - * @param int $duration the number of seconds in which the cached values will expire. 0 means never expire. - * @return array array of failed keys - */ - protected function setValues($data, $duration) - { - $result = apcu_store($data, null, $duration); - return is_array($result) ? array_keys($result) : []; - } - - /** - * Stores a value identified by a key into cache if the cache does not contain this key. - * This is the implementation of the method declared in the parent class. - * @param string $key the key identifying the value to be cached - * @param mixed $value the value to be cached. Most often it's a string. If you have disabled [[serializer]], - * it could be something else. - * @param int $duration the number of seconds in which the cached value will expire. 0 means never expire. - * @return bool true if the value is successfully stored into cache, false otherwise + * {@inheritdoc} */ - protected function addValue($key, $value, $duration) + protected function setValue($key, $value, $ttl) { - return apcu_add($key, $value, $duration); + return apcu_store($key, $value, $ttl); } /** - * Adds multiple key-value pairs to cache. - * @param array $data array where key corresponds to cache key while value is the value stored - * @param int $duration the number of seconds in which the cached values will expire. 0 means never expire. - * @return array array of failed keys + * {@inheritdoc} */ - protected function addValues($data, $duration) + protected function setValues($values, $ttl) { - $result = apcu_add($data, null, $duration); - return is_array($result) ? array_keys($result) : []; + $result = apcu_store($values, null, $ttl); + return is_array($result); } /** - * Deletes a value with the specified key from cache - * This is the implementation of the method declared in the parent class. - * @param string $key the key of the value to be deleted - * @return bool if no error happens during deletion + * {@inheritdoc} */ protected function deleteValue($key) { @@ -141,11 +105,9 @@ protected function deleteValue($key) } /** - * Deletes all values from cache. - * This is the implementation of the method declared in the parent class. - * @return bool whether the flush operation was successful. + * {@inheritdoc} */ - protected function flushValues() + public function clear() { return apcu_clear_cache(); } diff --git a/framework/caching/ArrayCache.php b/framework/caching/ArrayCache.php index e7de9d40da2..439dd9fa43a 100644 --- a/framework/caching/ArrayCache.php +++ b/framework/caching/ArrayCache.php @@ -10,9 +10,26 @@ /** * ArrayCache provides caching for the current request only by storing the values in an array. * - * See [[Cache]] for common cache operations that ArrayCache supports. + * Application configuration example: * - * Unlike the [[Cache]], ArrayCache allows the expire parameter of [[set]], [[add]], [[multiSet]] and [[multiAdd]] to + * ```php + * return [ + * 'components' => [ + * 'cache' => [ + * 'class' => yii\caching\Cache::class, + * 'handler' => [ + * 'class' => yii\caching\ArrayCache::class, + * ], + * ], + * // ... + * ], + * // ... + * ]; + * ``` + * + * See [[\Psr\SimpleCache\CacheInterface]] for common cache operations that ArrayCache supports. + * + * Unlike the [[Cache]], ArrayCache allows the expire parameter of [[set()]] and [[setMultiple()]] to * be a floating point number, so you may specify the time in milliseconds (e.g. 0.1 will be 100 milliseconds). * * For enhanced performance of ArrayCache, you can disable serialization of the stored data by setting [[$serializer]] to `false`. @@ -22,17 +39,20 @@ * @author Carsten Brandt * @since 2.0 */ -class ArrayCache extends Cache +class ArrayCache extends SimpleCache { - private $_cache; + /** + * @var array cached values. + */ + private $_cache = []; /** * @inheritdoc */ - public function exists($key) + public function has($key) { - $key = $this->buildKey($key); + $key = $this->normalizeKey($key); return isset($this->_cache[$key]) && ($this->_cache[$key][1] === 0 || $this->_cache[$key][1] > microtime(true)); } @@ -50,21 +70,9 @@ protected function getValue($key) /** * @inheritdoc */ - protected function setValue($key, $value, $duration) + protected function setValue($key, $value, $ttl) { - $this->_cache[$key] = [$value, $duration === 0 ? 0 : microtime(true) + $duration]; - return true; - } - - /** - * @inheritdoc - */ - protected function addValue($key, $value, $duration) - { - if (isset($this->_cache[$key]) && ($this->_cache[$key][1] === 0 || $this->_cache[$key][1] > microtime(true))) { - return false; - } - $this->_cache[$key] = [$value, $duration === 0 ? 0 : microtime(true) + $duration]; + $this->_cache[$key] = [$value, $ttl === 0 ? 0 : microtime(true) + $ttl]; return true; } @@ -80,7 +88,7 @@ protected function deleteValue($key) /** * @inheritdoc */ - protected function flushValues() + public function clear() { $this->_cache = []; return true; diff --git a/framework/caching/Cache.php b/framework/caching/Cache.php index f3f5eb81acc..282d1f64315 100644 --- a/framework/caching/Cache.php +++ b/framework/caching/Cache.php @@ -9,10 +9,31 @@ use Yii; use yii\base\Component; +use yii\di\Instance; use yii\helpers\StringHelper; /** - * Cache is the base class for cache classes supporting different cache storage implementations. + * Cache provides support for the data caching, including cache key composition and dependencies. + * The actual data caching is performed via [[handler]], which should be configured to be [[\Psr\SimpleCache\CacheInterface]] + * instance. + * + * Application configuration example: + * + * ```php + * return [ + * 'components' => [ + * 'cache' => [ + * 'class' => yii\caching\Cache::class, + * 'handler' => [ + * 'class' => yii\caching\FileCache::class, + * 'cachePath' => '@runtime/cache', + * ], + * ], + * // ... + * ], + * // ... + * ]; + * ``` * * A data item can be stored in the cache by calling [[set()]] and be retrieved back * later (in the same or different request) by [[get()]]. In both operations, @@ -25,7 +46,7 @@ * ```php * $key = 'demo'; * $data = $cache->get($key); - * if ($data === false) { + * if ($data === null) { * // ...generate $data here... * $cache->set($key, $data, $duration, $dependency); * } @@ -38,112 +59,79 @@ * echo $cache['foo']; * ``` * - * Derived classes should implement the following methods which do the actual cache storage operations: - * - * - [[getValue()]]: retrieve the value with a key (if any) from cache - * - [[setValue()]]: store the value with a key into cache - * - [[addValue()]]: store the value only if the cache does not have this key before - * - [[deleteValue()]]: delete the value with the specified key from cache - * - [[flushValues()]]: delete all values from cache - * - * For more details and usage information on Cache, see the [guide article on caching](guide:caching-overview). + * For more details and usage information on Cache, see the [guide article on caching](guide:caching-overview) + * and [PSR-16 specification](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-16-simple-cache.md). * * @author Qiang Xue * @since 2.0 */ -abstract class Cache extends Component implements CacheInterface +class Cache extends Component implements CacheInterface { /** - * @var string a string prefixed to every cache key so that it is unique globally in the whole cache storage. - * It is recommended that you set a unique cache key prefix for each application if the same cache - * storage is being used by different applications. - * - * To ensure interoperability, only alphanumeric characters should be used. - */ - public $keyPrefix; - /** - * @var null|array|false the functions used to serialize and unserialize cached data. Defaults to null, meaning - * using the default PHP `serialize()` and `unserialize()` functions. If you want to use some more efficient - * serializer (e.g. [igbinary](http://pecl.php.net/package/igbinary)), you may configure this property with - * a two-element array. The first element specifies the serialization function, and the second the deserialization - * function. If this property is set false, data will be directly sent to and retrieved from the underlying - * cache component without any serialization or deserialization. You should not turn off serialization if - * you are using [[Dependency|cache dependency]], because it relies on data serialization. Also, some - * implementations of the cache can not correctly save and retrieve data different from a string type. + * @var \Psr\SimpleCache\CacheInterface|array|\Closure|string actual cache handler or its DI compatible configuration. + * After the Cache object is created, if you want to change this property, you should only assign it + * with a [[\Psr\SimpleCache\CacheInterface]] instance. + * @since 2.1.0 */ - public $serializer; + public $handler; + + /** - * @var int default duration in seconds before a cache entry will expire. Default value is 0, meaning infinity. - * This value is used by [[set()]] if the duration is not explicitly given. - * @since 2.0.11 + * {@inheritdoc} */ - public $defaultDuration = 0; - + public function init() + { + parent::init(); + $this->handler = Instance::ensure($this->handler instanceof \Closure ? call_user_func($this->handler) : $this->handler, \Psr\SimpleCache\CacheInterface::class); + } /** * Builds a normalized cache key from a given key. * * If the given key is a string containing alphanumeric characters only and no more than 32 characters, - * then the key will be returned back prefixed with [[keyPrefix]]. Otherwise, a normalized key - * is generated by serializing the given key, applying MD5 hashing, and prefixing with [[keyPrefix]]. + * then the key will be returned back as it is. Otherwise, a normalized key is generated by serializing + * the given key and applying MD5 hashing. * * @param mixed $key the key to be normalized * @return string the generated cache key */ - public function buildKey($key) + protected function buildKey($key) { if (is_string($key)) { - $key = ctype_alnum($key) && StringHelper::byteLength($key) <= 32 ? $key : md5($key); - } else { - $key = md5(json_encode($key)); + return ctype_alnum($key) && StringHelper::byteLength($key) <= 32 ? $key : md5($key); } - - return $this->keyPrefix . $key; + return md5(json_encode($key)); } /** - * Retrieves a value from cache with a specified key. - * @param mixed $key a key identifying the cached value. This can be a simple string or - * a complex data structure consisting of factors representing the key. - * @return mixed the value stored in cache, false if the value is not in the cache, expired, - * or the dependency associated with the cached data has changed. + * {@inheritdoc} */ - public function get($key) + public function get($key, $default = null) { $key = $this->buildKey($key); - $value = $this->getValue($key); - if ($value === false || $this->serializer === false) { - return $value; - } elseif ($this->serializer === null) { - $value = unserialize($value); - } else { - $value = call_user_func($this->serializer[1], $value); + $value = $this->handler->get($key); + + if ($value === null) { + return $default; } - if (is_array($value) && !($value[1] instanceof Dependency && $value[1]->isChanged($this))) { + + if (is_array($value) && isset($value[1]) && $value[1] instanceof Dependency) { + if ($value[1]->isChanged($this)) { + return $default; + } return $value[0]; } - return false; + return $value; } /** - * Checks whether a specified key exists in the cache. - * This can be faster than getting the value from the cache if the data is big. - * In case a cache does not support this feature natively, this method will try to simulate it - * but has no performance improvement over getting it. - * Note that this method does not check whether the dependency associated - * with the cached data, if there is any, has changed. So a call to [[get]] - * may return false while exists returns true. - * @param mixed $key a key identifying the cached value. This can be a simple string or - * a complex data structure consisting of factors representing the key. - * @return bool true if a value exists in cache, false if the value is not in the cache or expired. + * {@inheritdoc} */ - public function exists($key) + public function has($key) { $key = $this->buildKey($key); - $value = $this->getValue($key); - - return $value !== false; + return $this->handler->has($key); } /** @@ -152,32 +140,32 @@ public function exists($key) * which may improve the performance. In case a cache does not support this feature natively, * this method will try to simulate it. * @param string[] $keys list of string keys identifying the cached values + * @param mixed $default Default value to return for keys that do not exist. * @return array list of cached values corresponding to the specified keys. The array * is returned in terms of (key, value) pairs. * If a value is not cached or expired, the corresponding array value will be false. * @since 2.0.7 */ - public function multiGet($keys) + public function getMultiple($keys, $default = null) { $keyMap = []; foreach ($keys as $key) { $keyMap[$key] = $this->buildKey($key); } - $values = $this->getValues(array_values($keyMap)); + $values = $this->handler->getMultiple(array_values($keyMap)); $results = []; foreach ($keyMap as $key => $newKey) { - $results[$key] = false; + $results[$key] = $default; if (isset($values[$newKey])) { - if ($this->serializer === false) { - $results[$key] = $values[$newKey]; - } else { - $value = $this->serializer === null ? unserialize($values[$newKey]) - : call_user_func($this->serializer[1], $values[$newKey]); - - if (is_array($value) && !($value[1] instanceof Dependency && $value[1]->isChanged($this))) { - $results[$key] = $value[0]; + $value = $values[$newKey]; + if (is_array($value) && isset($value[1]) && $value[1] instanceof Dependency) { + if ($value[1]->isChanged($this)) { + continue; + } else { + $value = $value[0]; } } + $results[$key] = $value; } } @@ -192,30 +180,20 @@ public function multiGet($keys) * @param mixed $key a key identifying the value to be cached. This can be a simple string or * a complex data structure consisting of factors representing the key. * @param mixed $value the value to be cached - * @param int $duration default duration in seconds before the cache will expire. If not set, - * default [[defaultDuration]] value is used. + * @param null|int|\DateInterval $ttl the TTL value of this item. If not set, default value is used. * @param Dependency $dependency dependency of the cached item. If the dependency changes, * the corresponding value in the cache will be invalidated when it is fetched via [[get()]]. * This parameter is ignored if [[serializer]] is false. * @return bool whether the value is successfully stored into cache */ - public function set($key, $value, $duration = null, $dependency = null) + public function set($key, $value, $ttl = null, $dependency = null) { - if ($duration === null) { - $duration = $this->defaultDuration; - } - - if ($dependency !== null && $this->serializer !== false) { + if ($dependency !== null) { $dependency->evaluateDependency($this); - } - if ($this->serializer === null) { - $value = serialize([$value, $dependency]); - } elseif ($this->serializer !== false) { - $value = call_user_func($this->serializer[0], [$value, $dependency]); + $value = [$value, $dependency]; } $key = $this->buildKey($key); - - return $this->setValue($key, $value, $duration); + return $this->handler->set($key, $value, $ttl); } /** @@ -224,65 +202,79 @@ public function set($key, $value, $duration = null, $dependency = null) * expiration time will be replaced with the new ones, respectively. * * @param array $items the items to be cached, as key-value pairs. - * @param int $duration default number of seconds in which the cached values will expire. 0 means never expire. + * @param null|int|\DateInterval $ttl the TTL value of this item. If not set, default value is used. * @param Dependency $dependency dependency of the cached items. If the dependency changes, * the corresponding values in the cache will be invalidated when it is fetched via [[get()]]. * This parameter is ignored if [[serializer]] is false. * @return array array of failed keys * @since 2.0.7 */ - public function multiSet($items, $duration = 0, $dependency = null) + public function setMultiple($items, $ttl = 0, $dependency = null) { - if ($dependency !== null && $this->serializer !== false) { + if ($dependency !== null) { $dependency->evaluateDependency($this); } $data = []; foreach ($items as $key => $value) { - if ($this->serializer === null) { - $value = serialize([$value, $dependency]); - } elseif ($this->serializer !== false) { - $value = call_user_func($this->serializer[0], [$value, $dependency]); + if ($dependency !== null) { + $value = [$value, $dependency]; } - $key = $this->buildKey($key); $data[$key] = $value; } - return $this->setValues($data, $duration); + return $this->handler->setMultiple($data, $ttl); + } + + /** + * {@inheritdoc} + * @since 2.1 + */ + public function deleteMultiple($keys) + { + $actualKeys = []; + foreach ($keys as $key) { + $actualKeys[] = $this->buildKey($key); + } + return $this->handler->deleteMultiple($actualKeys); } /** * Stores multiple items in cache. Each item contains a value identified by a key. * If the cache already contains such a key, the existing value and expiration time will be preserved. * - * @param array $items the items to be cached, as key-value pairs. - * @param int $duration default number of seconds in which the cached values will expire. 0 means never expire. + * @param array $values the items to be cached, as key-value pairs. + * @param null|int|\DateInterval $ttl the TTL value of this item. If not set, default value is used. * @param Dependency $dependency dependency of the cached items. If the dependency changes, * the corresponding values in the cache will be invalidated when it is fetched via [[get()]]. * This parameter is ignored if [[serializer]] is false. * @return array array of failed keys * @since 2.0.7 */ - public function multiAdd($items, $duration = 0, $dependency = null) + public function addMultiple($values, $ttl = 0, $dependency = null) { - if ($dependency !== null && $this->serializer !== false) { + if ($dependency !== null) { $dependency->evaluateDependency($this); } $data = []; - foreach ($items as $key => $value) { - if ($this->serializer === null) { - $value = serialize([$value, $dependency]); - } elseif ($this->serializer !== false) { - $value = call_user_func($this->serializer[0], [$value, $dependency]); + foreach ($values as $key => $value) { + if ($dependency !== null) { + $value = [$value, $dependency]; } $key = $this->buildKey($key); $data[$key] = $value; } - return $this->addValues($data, $duration); + $existingValues = $this->handler->getMultiple(array_keys($data)); + foreach ($existingValues as $key => $value) { + if ($value !== null) { + unset($data[$key]); + } + } + return $this->handler->setMultiple($data, $ttl); } /** @@ -291,25 +283,26 @@ public function multiAdd($items, $duration = 0, $dependency = null) * @param mixed $key a key identifying the value to be cached. This can be a simple string or * a complex data structure consisting of factors representing the key. * @param mixed $value the value to be cached - * @param int $duration the number of seconds in which the cached value will expire. 0 means never expire. + * @param null|int|\DateInterval $ttl the TTL value of this item. If not set, default value is used. * @param Dependency $dependency dependency of the cached item. If the dependency changes, * the corresponding value in the cache will be invalidated when it is fetched via [[get()]]. * This parameter is ignored if [[serializer]] is false. * @return bool whether the value is successfully stored into cache */ - public function add($key, $value, $duration = 0, $dependency = null) + public function add($key, $value, $ttl = null, $dependency = null) { - if ($dependency !== null && $this->serializer !== false) { + if ($dependency !== null) { $dependency->evaluateDependency($this); + $value = [$value, $dependency]; } - if ($this->serializer === null) { - $value = serialize([$value, $dependency]); - } elseif ($this->serializer !== false) { - $value = call_user_func($this->serializer[0], [$value, $dependency]); - } + $key = $this->buildKey($key); - return $this->addValue($key, $value, $duration); + if ($this->handler->has($key)) { + return false; + } + + return $this->handler->set($key, $value, $ttl); } /** @@ -322,7 +315,7 @@ public function delete($key) { $key = $this->buildKey($key); - return $this->deleteValue($key); + return $this->handler->delete($key); } /** @@ -330,116 +323,9 @@ public function delete($key) * Be careful of performing this operation if the cache is shared among multiple applications. * @return bool whether the flush operation was successful. */ - public function flush() - { - return $this->flushValues(); - } - - /** - * Retrieves a value from cache with a specified key. - * This method should be implemented by child classes to retrieve the data - * from specific cache storage. - * @param string $key a unique key identifying the cached value - * @return mixed|false the value stored in cache, false if the value is not in the cache or expired. Most often - * value is a string. If you have disabled [[serializer]], it could be something else. - */ - abstract protected function getValue($key); - - /** - * Stores a value identified by a key in cache. - * This method should be implemented by child classes to store the data - * in specific cache storage. - * @param string $key the key identifying the value to be cached - * @param mixed $value the value to be cached. Most often it's a string. If you have disabled [[serializer]], - * it could be something else. - * @param int $duration the number of seconds in which the cached value will expire. 0 means never expire. - * @return bool true if the value is successfully stored into cache, false otherwise - */ - abstract protected function setValue($key, $value, $duration); - - /** - * Stores a value identified by a key into cache if the cache does not contain this key. - * This method should be implemented by child classes to store the data - * in specific cache storage. - * @param string $key the key identifying the value to be cached - * @param mixed $value the value to be cached. Most often it's a string. If you have disabled [[serializer]], - * it could be something else. - * @param int $duration the number of seconds in which the cached value will expire. 0 means never expire. - * @return bool true if the value is successfully stored into cache, false otherwise - */ - abstract protected function addValue($key, $value, $duration); - - /** - * Deletes a value with the specified key from cache - * This method should be implemented by child classes to delete the data from actual cache storage. - * @param string $key the key of the value to be deleted - * @return bool if no error happens during deletion - */ - abstract protected function deleteValue($key); - - /** - * Deletes all values from cache. - * Child classes may implement this method to realize the flush operation. - * @return bool whether the flush operation was successful. - */ - abstract protected function flushValues(); - - /** - * Retrieves multiple values from cache with the specified keys. - * The default implementation calls [[getValue()]] multiple times to retrieve - * the cached values one by one. If the underlying cache storage supports multiget, - * this method should be overridden to exploit that feature. - * @param array $keys a list of keys identifying the cached values - * @return array a list of cached values indexed by the keys - */ - protected function getValues($keys) - { - $results = []; - foreach ($keys as $key) { - $results[$key] = $this->getValue($key); - } - - return $results; - } - - /** - * Stores multiple key-value pairs in cache. - * The default implementation calls [[setValue()]] multiple times store values one by one. If the underlying cache - * storage supports multi-set, this method should be overridden to exploit that feature. - * @param array $data array where key corresponds to cache key while value is the value stored - * @param int $duration the number of seconds in which the cached values will expire. 0 means never expire. - * @return array array of failed keys - */ - protected function setValues($data, $duration) + public function clear() { - $failedKeys = []; - foreach ($data as $key => $value) { - if ($this->setValue($key, $value, $duration) === false) { - $failedKeys[] = $key; - } - } - - return $failedKeys; - } - - /** - * Adds multiple key-value pairs to cache. - * The default implementation calls [[addValue()]] multiple times add values one by one. If the underlying cache - * storage supports multi-add, this method should be overridden to exploit that feature. - * @param array $data array where key corresponds to cache key while value is the value stored. - * @param int $duration the number of seconds in which the cached values will expire. 0 means never expire. - * @return array array of failed keys - */ - protected function addValues($data, $duration) - { - $failedKeys = []; - foreach ($data as $key => $value) { - if ($this->addValue($key, $value, $duration) === false) { - $failedKeys[] = $key; - } - } - - return $failedKeys; + return $this->handler->clear(); } /** @@ -506,22 +392,21 @@ public function offsetUnset($key) * a complex data structure consisting of factors representing the key. * @param callable|\Closure $callable the callable or closure that will be used to generate a value to be cached. * In case $callable returns `false`, the value will not be cached. - * @param int $duration default duration in seconds before the cache will expire. If not set, - * [[defaultDuration]] value will be used. + * @param null|int|\DateInterval $ttl the TTL value of this item. If not set, default value is used. * @param Dependency $dependency dependency of the cached item. If the dependency changes, * the corresponding value in the cache will be invalidated when it is fetched via [[get()]]. * This parameter is ignored if [[serializer]] is `false`. * @return mixed result of $callable execution * @since 2.0.11 */ - public function getOrSet($key, $callable, $duration = null, $dependency = null) + public function getOrSet($key, $callable, $ttl = null, $dependency = null) { - if (($value = $this->get($key)) !== false) { + if (($value = $this->get($key)) !== null) { return $value; } $value = call_user_func($callable, $this); - if (!$this->set($key, $value, $duration, $dependency)) { + if (!$this->set($key, $value, $ttl, $dependency)) { Yii::warning('Failed to set cache value for key ' . json_encode($key), __METHOD__); } diff --git a/framework/caching/CacheInterface.php b/framework/caching/CacheInterface.php index 426724044a0..13eff214fc0 100644 --- a/framework/caching/CacheInterface.php +++ b/framework/caching/CacheInterface.php @@ -8,7 +8,8 @@ namespace yii\caching; /** - * CacheInterface is the base interface for cache. + * CacheInterface defines the common interface to be implemented by cache classes. + * It extends [[\Psr\SimpleCache\CacheInterface]] adding ability for cache dependency specification. * * A data item can be stored in the cache by calling [[set()]] and be retrieved back * later (in the same or different request) by [[get()]]. In both operations, @@ -21,7 +22,7 @@ * ```php * $key = 'demo'; * $data = $cache->get($key); - * if ($data === false) { + * if ($data === null) { * // ...generate $data here... * $cache->set($key, $data, $duration, $dependency); * } @@ -34,61 +35,18 @@ * echo $cache['foo']; * ``` * - * For more details and usage information on Cache, see the [guide article on caching](guide:caching-overview). + * For more details and usage information on Cache, see the [guide article on caching](guide:caching-overview) + * and [PSR-16 specification](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-16-simple-cache.md). + * + * @see \Psr\SimpleCache\CacheInterface * * @author Qiang Xue * @author Dmitry Naumenko - * @since 2.0.13. Previous framework versions used abstract class [[yii\caching\Cache]] as interface. + * @author Paul Klimov + * @since 2.0.13. Previous framework versions used abstract class [[\yii\caching\Cache]] as interface. */ -interface CacheInterface extends \ArrayAccess +interface CacheInterface extends \Psr\SimpleCache\CacheInterface, \ArrayAccess { - /** - * Builds a normalized cache key from a given key. - * - * If the given key is a string containing alphanumeric characters only and no more than 32 characters, - * then the key will be returned back prefixed with [[keyPrefix]]. Otherwise, a normalized key - * is generated by serializing the given key, applying MD5 hashing, and prefixing with [[keyPrefix]]. - * - * @param mixed $key the key to be normalized - * @return string the generated cache key - */ - public function buildKey($key); - - /** - * Retrieves a value from cache with a specified key. - * @param mixed $key a key identifying the cached value. This can be a simple string or - * a complex data structure consisting of factors representing the key. - * @return mixed the value stored in cache, false if the value is not in the cache, expired, - * or the dependency associated with the cached data has changed. - */ - public function get($key); - - /** - * Checks whether a specified key exists in the cache. - * This can be faster than getting the value from the cache if the data is big. - * In case a cache does not support this feature natively, this method will try to simulate it - * but has no performance improvement over getting it. - * Note that this method does not check whether the dependency associated - * with the cached data, if there is any, has changed. So a call to [[get]] - * may return false while exists returns true. - * @param mixed $key a key identifying the cached value. This can be a simple string or - * a complex data structure consisting of factors representing the key. - * @return bool true if a value exists in cache, false if the value is not in the cache or expired. - */ - public function exists($key); - - /** - * Retrieves multiple values from cache with the specified keys. - * Some caches (such as memcache, apc) allow retrieving multiple cached values at the same time, - * which may improve the performance. In case a cache does not support this feature natively, - * this method will try to simulate it. - * @param string[] $keys list of string keys identifying the cached values - * @return array list of cached values corresponding to the specified keys. The array - * is returned in terms of (key, value) pairs. - * If a value is not cached or expired, the corresponding array value will be false. - */ - public function multiGet($keys); - /** * Stores a value identified by a key into cache. * If the cache already contains such a key, the existing value and @@ -97,14 +55,13 @@ public function multiGet($keys); * @param mixed $key a key identifying the value to be cached. This can be a simple string or * a complex data structure consisting of factors representing the key. * @param mixed $value the value to be cached - * @param int $duration default duration in seconds before the cache will expire. If not set, - * default [[defaultDuration]] value is used. + * @param null|int|\DateInterval $ttl the TTL value of this item. If not set, default value is used. * @param Dependency $dependency dependency of the cached item. If the dependency changes, * the corresponding value in the cache will be invalidated when it is fetched via [[get()]]. * This parameter is ignored if [[serializer]] is false. * @return bool whether the value is successfully stored into cache */ - public function set($key, $value, $duration = null, $dependency = null); + public function set($key, $value, $ttl = null, $dependency = null); /** * Stores multiple items in cache. Each item contains a value identified by a key. @@ -112,13 +69,13 @@ public function set($key, $value, $duration = null, $dependency = null); * expiration time will be replaced with the new ones, respectively. * * @param array $items the items to be cached, as key-value pairs. - * @param int $duration default number of seconds in which the cached values will expire. 0 means never expire. + * @param null|int|\DateInterval $ttl the TTL value of this item. If not set, default value is used. * @param Dependency $dependency dependency of the cached items. If the dependency changes, * the corresponding values in the cache will be invalidated when it is fetched via [[get()]]. * This parameter is ignored if [[serializer]] is false. * @return array array of failed keys */ - public function multiSet($items, $duration = 0, $dependency = null); + public function setMultiple($items, $ttl = null, $dependency = null); /** * Stores a value identified by a key into cache if the cache does not contain this key. @@ -126,41 +83,26 @@ public function multiSet($items, $duration = 0, $dependency = null); * @param mixed $key a key identifying the value to be cached. This can be a simple string or * a complex data structure consisting of factors representing the key. * @param mixed $value the value to be cached - * @param int $duration the number of seconds in which the cached value will expire. 0 means never expire. + * @param null|int|\DateInterval $ttl the TTL value of this item. If not set, default value is used. * @param Dependency $dependency dependency of the cached item. If the dependency changes, * the corresponding value in the cache will be invalidated when it is fetched via [[get()]]. * This parameter is ignored if [[serializer]] is false. * @return bool whether the value is successfully stored into cache */ - public function add($key, $value, $duration = 0, $dependency = null); + public function add($key, $value, $ttl = 0, $dependency = null); /** * Stores multiple items in cache. Each item contains a value identified by a key. * If the cache already contains such a key, the existing value and expiration time will be preserved. * - * @param array $items the items to be cached, as key-value pairs. - * @param int $duration default number of seconds in which the cached values will expire. 0 means never expire. + * @param array $values the items to be cached, as key-value pairs. + * @param null|int|\DateInterval $ttl the TTL value of this item. If not set, default value is used. * @param Dependency $dependency dependency of the cached items. If the dependency changes, * the corresponding values in the cache will be invalidated when it is fetched via [[get()]]. * This parameter is ignored if [[serializer]] is false. * @return array array of failed keys */ - public function multiAdd($items, $duration = 0, $dependency = null); - - /** - * Deletes a value with the specified key from cache - * @param mixed $key a key identifying the value to be deleted from cache. This can be a simple string or - * a complex data structure consisting of factors representing the key. - * @return bool if no error happens during deletion - */ - public function delete($key); - - /** - * Deletes all values from cache. - * Be careful of performing this operation if the cache is shared among multiple applications. - * @return bool whether the flush operation was successful. - */ - public function flush(); + public function addMultiple($values, $ttl = 0, $dependency = null); /** * Method combines both [[set()]] and [[get()]] methods to retrieve value identified by a $key, @@ -181,12 +123,11 @@ public function flush(); * a complex data structure consisting of factors representing the key. * @param callable|\Closure $callable the callable or closure that will be used to generate a value to be cached. * In case $callable returns `false`, the value will not be cached. - * @param int $duration default duration in seconds before the cache will expire. If not set, - * [[defaultDuration]] value will be used. + * @param null|int|\DateInterval $ttl the TTL value of this item. If not set, default value is used. * @param Dependency $dependency dependency of the cached item. If the dependency changes, * the corresponding value in the cache will be invalidated when it is fetched via [[get()]]. * This parameter is ignored if [[serializer]] is `false`. * @return mixed result of $callable execution */ - public function getOrSet($key, $callable, $duration = null, $dependency = null); + public function getOrSet($key, $callable, $ttl = null, $dependency = null); } diff --git a/framework/caching/DbCache.php b/framework/caching/DbCache.php index 3a4ec8002b4..20c1a60c89c 100644 --- a/framework/caching/DbCache.php +++ b/framework/caching/DbCache.php @@ -19,16 +19,25 @@ * By default, DbCache stores session data in a DB table named 'cache'. This table * must be pre-created. The table name can be changed by setting [[cacheTable]]. * - * Please refer to [[Cache]] for common cache operations that are supported by DbCache. + * Please refer to [[\Psr\SimpleCache\CacheInterface]] for common cache operations that are supported by DbCache. * * The following example shows how you can configure the application to use DbCache: * * ```php - * 'cache' => [ - * 'class' => \yii\caching\DbCache::class, - * // 'db' => 'mydb', - * // 'cacheTable' => 'my_cache', - * ] + * return [ + * 'components' => [ + * 'cache' => [ + * 'class' => yii\caching\Cache:class, + * 'handler' => [ + * 'class' => yii\caching\DbCache::class, + * // 'db' => 'mydb', + * // 'cacheTable' => 'my_cache', + * ], + * ], + * // ... + * ], + * // ... + * ]; * ``` * * For more details and usage information on Cache, see the [guide article on caching](guide:caching-overview). @@ -36,7 +45,7 @@ * @author Qiang Xue * @since 2.0 */ -class DbCache extends Cache +class DbCache extends SimpleCache { /** * @var Connection|array|string the DB connection object or the application component ID of the DB connection. @@ -88,18 +97,11 @@ public function init() } /** - * Checks whether a specified key exists in the cache. - * This can be faster than getting the value from the cache if the data is big. - * Note that this method does not check whether the dependency associated - * with the cached data, if there is any, has changed. So a call to [[get]] - * may return false while exists returns true. - * @param mixed $key a key identifying the cached value. This can be a simple string or - * a complex data structure consisting of factors representing the key. - * @return bool true if a value exists in cache, false if the value is not in the cache or expired. + * {@inheritdoc} */ - public function exists($key) + public function has($key) { - $key = $this->buildKey($key); + $key = $this->normalizeKey($key); $query = new Query(); $query->select(['COUNT(*)']) @@ -118,40 +120,36 @@ public function exists($key) } /** - * Retrieves a value from cache with a specified key. - * This is the implementation of the method declared in the parent class. - * @param string $key a unique key identifying the cached value - * @return string|false the value stored in cache, false if the value is not in the cache or expired. + * {@inheritdoc} */ protected function getValue($key) { - $query = new Query(); - $query->select(['data']) + $query = (new Query()) + ->select(['data']) ->from($this->cacheTable) ->where('[[id]] = :id AND ([[expire]] = 0 OR [[expire]] >' . time() . ')', [':id' => $key]); + if ($this->db->enableQueryCache) { // temporarily disable and re-enable query caching $this->db->enableQueryCache = false; $result = $query->createCommand($this->db)->queryScalar(); $this->db->enableQueryCache = true; - return $result; } + return $query->createCommand($this->db)->queryScalar(); } /** - * Retrieves multiple values from cache with the specified keys. - * @param array $keys a list of keys identifying the cached values - * @return array a list of cached values indexed by the keys + * {@inheritdoc} */ protected function getValues($keys) { if (empty($keys)) { return []; } - $query = new Query(); - $query->select(['id', 'data']) + $query = (new Query()) + ->select(['id', 'data']) ->from($this->cacheTable) ->where(['id' => $keys]) ->andWhere('([[expire]] = 0 OR [[expire]] > ' . time() . ')'); @@ -164,10 +162,7 @@ protected function getValues($keys) $rows = $query->createCommand($this->db)->queryAll(); } - $results = []; - foreach ($keys as $key) { - $results[$key] = false; - } + $results = array_fill_keys($keys, false); foreach ($rows as $row) { $results[$row['id']] = $row['data']; } @@ -176,20 +171,14 @@ protected function getValues($keys) } /** - * Stores a value identified by a key in cache. - * This is the implementation of the method declared in the parent class. - * - * @param string $key the key identifying the value to be cached - * @param string $value the value to be cached. Other types (if you have disabled [[serializer]]) cannot be saved. - * @param int $duration the number of seconds in which the cached value will expire. 0 means never expire. - * @return bool true if the value is successfully stored into cache, false otherwise + * {@inheritdoc} */ - protected function setValue($key, $value, $duration) + protected function setValue($key, $value, $ttl) { - $result = $this->db->noCache(function (Connection $db) use ($key, $value, $duration) { + $result = $this->db->noCache(function (Connection $db) use ($key, $value, $ttl) { $command = $db->createCommand() ->update($this->cacheTable, [ - 'expire' => $duration > 0 ? $duration + time() : 0, + 'expire' => $ttl > 0 ? $ttl + time() : 0, 'data' => [$value, \PDO::PARAM_LOB], ], ['id' => $key]); return $command->execute(); @@ -197,10 +186,9 @@ protected function setValue($key, $value, $duration) if ($result) { $this->gc(); - return true; } - return $this->addValue($key, $value, $duration); + return $this->addValue($key, $value, $ttl); } /** @@ -233,10 +221,7 @@ protected function addValue($key, $value, $duration) } /** - * Deletes a value with the specified key from cache - * This is the implementation of the method declared in the parent class. - * @param string $key the key of the value to be deleted - * @return bool if no error happens during deletion + * {@inheritdoc} */ protected function deleteValue($key) { @@ -264,11 +249,9 @@ public function gc($force = false) } /** - * Deletes all values from cache. - * This is the implementation of the method declared in the parent class. - * @return bool whether the flush operation was successful. + * {@inheritdoc} */ - protected function flushValues() + public function clear() { $this->db->createCommand() ->delete($this->cacheTable) diff --git a/framework/caching/DummyCache.php b/framework/caching/DummyCache.php index b8db22bc389..a0f23538c16 100644 --- a/framework/caching/DummyCache.php +++ b/framework/caching/DummyCache.php @@ -7,9 +7,28 @@ namespace yii\caching; +use yii\base\Component; + /** * DummyCache is a placeholder cache component. * + * Application configuration example: + * + * ```php + * return [ + * 'components' => [ + * 'cache' => [ + * 'class' => yii\caching\Cache::class, + * 'handler' => [ + * 'class' => yii\caching\DummyCache::class, + * ], + * ], + * // ... + * ], + * // ... + * ]; + * ``` + * * DummyCache does not cache anything. It is provided so that one can always configure * a 'cache' application component and save the check of existence of `\Yii::$app->cache`. * By replacing DummyCache with some other cache component, one can quickly switch from @@ -20,63 +39,68 @@ * @author Qiang Xue * @since 2.0 */ -class DummyCache extends Cache +class DummyCache extends Component implements \Psr\SimpleCache\CacheInterface { /** - * Retrieves a value from cache with a specified key. - * This is the implementation of the method declared in the parent class. - * @param string $key a unique key identifying the cached value - * @return mixed|false the value stored in cache, false if the value is not in the cache or expired. + * {@inheritdoc} */ - protected function getValue($key) + public function has($key) { return false; } /** - * Stores a value identified by a key in cache. - * This is the implementation of the method declared in the parent class. - * - * @param string $key the key identifying the value to be cached - * @param mixed $value the value to be cached - * @param int $duration the number of seconds in which the cached value will expire. 0 means never expire. - * @return bool true if the value is successfully stored into cache, false otherwise + * {@inheritdoc} + */ + public function get($key, $default = null) + { + return $default; + } + + /** + * {@inheritdoc} */ - protected function setValue($key, $value, $duration) + public function set($key, $value, $ttl = null) { return true; } /** - * Stores a value identified by a key into cache if the cache does not contain this key. - * This is the implementation of the method declared in the parent class. - * @param string $key the key identifying the value to be cached - * @param mixed $value the value to be cached - * @param int $duration the number of seconds in which the cached value will expire. 0 means never expire. - * @return bool true if the value is successfully stored into cache, false otherwise + * {@inheritdoc} */ - protected function addValue($key, $value, $duration) + public function delete($key) { return true; } /** - * Deletes a value with the specified key from cache - * This is the implementation of the method declared in the parent class. - * @param string $key the key of the value to be deleted - * @return bool if no error happens during deletion + * {@inheritdoc} + */ + public function clear() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function getMultiple($keys, $default = null) + { + return array_fill_keys($keys, $default); + } + + /** + * {@inheritdoc} */ - protected function deleteValue($key) + public function setMultiple($values, $ttl = null) { return true; } /** - * Deletes all values from cache. - * This is the implementation of the method declared in the parent class. - * @return bool whether the flush operation was successful. + * {@inheritdoc} */ - protected function flushValues() + public function deleteMultiple($keys) { return true; } diff --git a/framework/caching/Exception.php b/framework/caching/Exception.php new file mode 100644 index 00000000000..5304827e404 --- /dev/null +++ b/framework/caching/Exception.php @@ -0,0 +1,25 @@ + + * @since 2.1.0 + */ +class Exception extends \yii\base\Exception implements \Psr\SimpleCache\CacheException +{ + /** + * {@inheritdoc} + */ + public function getName() + { + return 'Cache Exception'; + } +} \ No newline at end of file diff --git a/framework/caching/FileCache.php b/framework/caching/FileCache.php index d884f8097d4..fa83a23d16f 100644 --- a/framework/caching/FileCache.php +++ b/framework/caching/FileCache.php @@ -11,29 +11,39 @@ use yii\helpers\FileHelper; /** - * FileCache implements a cache component using files. + * FileCache implements a cache handler using files. * * For each data value being cached, FileCache will store it in a separate file. * The cache files are placed under [[cachePath]]. FileCache will perform garbage collection * automatically to remove expired cache files. * - * Please refer to [[Cache]] for common cache operations that are supported by FileCache. + * Application configuration example: + * + * ```php + * return [ + * 'components' => [ + * 'cache' => [ + * 'class' => yii\caching\Cache::class, + * 'handler' => [ + * 'class' => yii\caching\FileCache::class, + * // 'cachePath' => '@runtime/cache', + * ], + * ], + * // ... + * ], + * // ... + * ]; + * ``` + * + * Please refer to [[\Psr\SimpleCache\CacheInterface]] for common cache operations that are supported by FileCache. * * For more details and usage information on Cache, see the [guide article on caching](guide:caching-overview). * * @author Qiang Xue * @since 2.0 */ -class FileCache extends Cache +class FileCache extends SimpleCache { - /** - * @var string a string prefixed to every cache key. This is needed when you store - * cache data under the same [[cachePath]] for different applications to avoid - * conflict. - * - * To ensure interoperability, only alphanumeric characters should be used. - */ - public $keyPrefix = ''; /** * @var string the directory to store cache files. You may use [path alias](guide:concept-aliases) here. * If not set, it will use the "cache" subdirectory under the application runtime path. @@ -84,27 +94,17 @@ public function init() } /** - * Checks whether a specified key exists in the cache. - * This can be faster than getting the value from the cache if the data is big. - * Note that this method does not check whether the dependency associated - * with the cached data, if there is any, has changed. So a call to [[get]] - * may return false while exists returns true. - * @param mixed $key a key identifying the cached value. This can be a simple string or - * a complex data structure consisting of factors representing the key. - * @return bool true if a value exists in cache, false if the value is not in the cache or expired. + * {@inheritdoc} */ - public function exists($key) + public function has($key) { - $cacheFile = $this->getCacheFile($this->buildKey($key)); + $cacheFile = $this->getCacheFile($this->normalizeKey($key)); return @filemtime($cacheFile) > time(); } /** - * Retrieves a value from cache with a specified key. - * This is the implementation of the method declared in the parent class. - * @param string $key a unique key identifying the cached value - * @return string|false the value stored in cache, false if the value is not in the cache or expired. + * {@inheritdoc} */ protected function getValue($key) { @@ -125,16 +125,9 @@ protected function getValue($key) } /** - * Stores a value identified by a key in cache. - * This is the implementation of the method declared in the parent class. - * - * @param string $key the key identifying the value to be cached - * @param string $value the value to be cached. Other types (If you have disabled [[serializer]]) unable to get is - * correct in [[getValue()]]. - * @param int $duration the number of seconds in which the cached value will expire. 0 means never expire. - * @return bool true if the value is successfully stored into cache, false otherwise + * {@inheritdoc} */ - protected function setValue($key, $value, $duration) + protected function setValue($key, $value, $ttl) { $this->gc(); $cacheFile = $this->getCacheFile($key); @@ -145,11 +138,11 @@ protected function setValue($key, $value, $duration) if ($this->fileMode !== null) { @chmod($cacheFile, $this->fileMode); } - if ($duration <= 0) { - $duration = 31536000; // 1 year + if ($ttl <= 0) { + $ttl = 31536000; // 1 year } - return @touch($cacheFile, $duration + time()); + return @touch($cacheFile, $ttl + time()); } $error = error_get_last(); @@ -158,35 +151,11 @@ protected function setValue($key, $value, $duration) } /** - * Stores a value identified by a key into cache if the cache does not contain this key. - * This is the implementation of the method declared in the parent class. - * - * @param string $key the key identifying the value to be cached - * @param string $value the value to be cached. Other types (if you have disabled [[serializer]]) unable to get is - * correct in [[getValue()]]. - * @param int $duration the number of seconds in which the cached value will expire. 0 means never expire. - * @return bool true if the value is successfully stored into cache, false otherwise - */ - protected function addValue($key, $value, $duration) - { - $cacheFile = $this->getCacheFile($key); - if (@filemtime($cacheFile) > time()) { - return false; - } - - return $this->setValue($key, $value, $duration); - } - - /** - * Deletes a value with the specified key from cache - * This is the implementation of the method declared in the parent class. - * @param string $key the key of the value to be deleted - * @return bool if no error happens during deletion + * {@inheritdoc} */ protected function deleteValue($key) { $cacheFile = $this->getCacheFile($key); - return @unlink($cacheFile); } @@ -212,14 +181,11 @@ protected function getCacheFile($key) } /** - * Deletes all values from cache. - * This is the implementation of the method declared in the parent class. - * @return bool whether the flush operation was successful. + * {@inheritdoc} */ - protected function flushValues() + public function clear() { $this->gc(true, false); - return true; } diff --git a/framework/caching/MemCached.php b/framework/caching/MemCached.php index 393074c58e5..5b5cc0c6e32 100644 --- a/framework/caching/MemCached.php +++ b/framework/caching/MemCached.php @@ -17,7 +17,7 @@ * MemCached can be configured with a list of memcached servers by settings its [[servers]] property. * By default, MemCached assumes there is a memcached server running on localhost at port 11211. * - * See [[Cache]] for common cache operations that MemCached supports. + * See [[\Psr\SimpleCache\CacheInterface]] for common cache operations that MemCached supports. * * Note, there is no security measure to protected data in memcached. * All data in memcached can be accessed by any process running in the system. @@ -28,17 +28,20 @@ * [ * 'components' => [ * 'cache' => [ - * 'class' => \yii\caching\MemCached::class, - * 'servers' => [ - * [ - * 'host' => 'server1', - * 'port' => 11211, - * 'weight' => 60, - * ], - * [ - * 'host' => 'server2', - * 'port' => 11211, - * 'weight' => 40, + * 'class' => \yii\caching\Cache::class, + * 'handler' => [ + * 'class' => \yii\caching\MemCached::class, + * 'servers' => [ + * [ + * 'host' => 'server1', + * 'port' => 11211, + * 'weight' => 60, + * ], + * [ + * 'host' => 'server2', + * 'port' => 11211, + * 'weight' => 40, + * ], * ], * ], * ], @@ -59,7 +62,7 @@ * @author Qiang Xue * @since 2.0 */ -class MemCached extends Cache +class MemCached extends SimpleCache { /** * @var string an ID that identifies a Memcached instance. @@ -187,10 +190,7 @@ public function setServers($config) } /** - * Retrieves a value from cache with a specified key. - * This is the implementation of the method declared in the parent class. - * @param string $key a unique key identifying the cached value - * @return mixed|false the value stored in cache, false if the value is not in the cache or expired. + * {@inheritdoc} */ protected function getValue($key) { @@ -198,9 +198,7 @@ protected function getValue($key) } /** - * Retrieves multiple values from cache with the specified keys. - * @param array $keys a list of keys identifying the cached values - * @return array a list of cached values indexed by the keys + * {@inheritdoc} */ protected function getValues($keys) { @@ -208,65 +206,33 @@ protected function getValues($keys) } /** - * Stores a value identified by a key in cache. - * This is the implementation of the method declared in the parent class. - * - * @param string $key the key identifying the value to be cached - * @param mixed $value the value to be cached. - * @see [Memcached::set()](http://php.net/manual/en/memcached.set.php) - * @param int $duration the number of seconds in which the cached value will expire. 0 means never expire. - * @return bool true if the value is successfully stored into cache, false otherwise + * {@inheritdoc} */ - protected function setValue($key, $value, $duration) + protected function setValue($key, $value, $ttl) { // Use UNIX timestamp since it doesn't have any limitation // @see http://php.net/manual/en/memcached.expiration.php - $expire = $duration > 0 ? $duration + time() : 0; + $expire = $ttl > 0 ? $ttl + time() : 0; return $this->_cache->set($key, $value, $expire); } /** - * Stores multiple key-value pairs in cache. - * @param array $data array where key corresponds to cache key while value is the value stored - * @param int $duration the number of seconds in which the cached values will expire. 0 means never expire. - * @return array array of failed keys. + * {@inheritdoc} */ - protected function setValues($data, $duration) + protected function setValues($values, $ttl) { // Use UNIX timestamp since it doesn't have any limitation // @see http://php.net/manual/en/memcached.expiration.php - $expire = $duration > 0 ? $duration + time() : 0; + $expire = $ttl > 0 ? $ttl + time() : 0; // Memcached::setMulti() returns boolean // @see http://php.net/manual/en/memcached.setmulti.php - return $this->_cache->setMulti($data, $expire) ? [] : array_keys($data); - } - - /** - * Stores a value identified by a key into cache if the cache does not contain this key. - * This is the implementation of the method declared in the parent class. - * - * @param string $key the key identifying the value to be cached - * @param mixed $value the value to be cached - * @see [Memcached::set()](http://php.net/manual/en/memcached.set.php) - * @param int $duration the number of seconds in which the cached value will expire. 0 means never expire. - * @return bool true if the value is successfully stored into cache, false otherwise - */ - protected function addValue($key, $value, $duration) - { - // Use UNIX timestamp since it doesn't have any limitation - // @see http://php.net/manual/en/memcached.expiration.php - $expire = $duration > 0 ? $duration + time() : 0; - - return $this->_cache->add($key, $value, $expire); + return $this->_cache->setMulti($values, $expire) ? [] : array_keys($values); } /** - * Deletes a value with the specified key from cache - * This is the implementation of the method declared in the parent class. - * @param string $key the key of the value to be deleted - * @return bool if no error happens during deletion + * {@inheritdoc} */ protected function deleteValue($key) { @@ -274,11 +240,9 @@ protected function deleteValue($key) } /** - * Deletes all values from cache. - * This is the implementation of the method declared in the parent class. - * @return bool whether the flush operation was successful. + * {@inheritdoc} */ - protected function flushValues() + public function clear() { return $this->_cache->flush(); } diff --git a/framework/caching/SimpleCache.php b/framework/caching/SimpleCache.php new file mode 100644 index 00000000000..60ab5214429 --- /dev/null +++ b/framework/caching/SimpleCache.php @@ -0,0 +1,270 @@ + + * @since 2.1.0 + */ +abstract class SimpleCache extends Component implements CacheInterface +{ + /** + * @var int default TTL for a cache entry. Default value is 0, meaning infinity. + * This value is used by [[set()]] and [[setMultiple()]], if the duration is not explicitly given. + */ + public $defaultTtl = 0; + /** + * @var string a string prefixed to every cache key so that it is unique globally in the whole cache storage. + * It is recommended that you set a unique cache key prefix for each application if the same cache + * storage is being used by different applications. + * + * To ensure interoperability, only alphanumeric characters should be used. + */ + public $keyPrefix = ''; + /** + * @var null|array|false the functions used to serialize and unserialize cached data. Defaults to null, meaning + * using the default PHP `serialize()` and `unserialize()` functions. If you want to use some more efficient + * serializer (e.g. [igbinary](http://pecl.php.net/package/igbinary)), you may configure this property with + * a two-element array. The first element specifies the serialization function, and the second the deserialization + * function. If this property is set false, data will be directly sent to and retrieved from the underlying + * cache component without any serialization or deserialization. You should not turn off serialization if + * you are using [[Dependency|cache dependency]], because it relies on data serialization. Also, some + * implementations of the cache can not correctly save and retrieve data different from a string type. + */ + public $serializer; + + + /** + * {@inheritdoc} + */ + public function get($key, $default = null) + { + $key = $this->normalizeKey($key); + $value = $this->getValue($key); + if ($value === false || $this->serializer === false) { + return $default; + } elseif ($this->serializer === null) { + return unserialize($value); + } + + return call_user_func($this->serializer[1], $value); + } + + /** + * {@inheritdoc} + */ + public function getMultiple($keys, $default = null) + { + $keyMap = []; + foreach ($keys as $key) { + $keyMap[$key] = $this->normalizeKey($key); + } + $values = $this->getValues(array_values($keyMap)); + $results = []; + foreach ($keyMap as $key => $newKey) { + $results[$key] = $default; + if (isset($values[$newKey]) && $values[$newKey] !== false) { + if ($this->serializer === false) { + $results[$key] = $values[$newKey]; + } else { + $results[$key] = $this->serializer === null ? unserialize($values[$newKey]) + : call_user_func($this->serializer[1], $values[$newKey]); + } + } + } + return $results; + } + + /** + * {@inheritdoc} + */ + public function has($key) + { + $key = $this->normalizeKey($key); + $value = $this->getValue($key); + return $value !== false; + } + + /** + * {@inheritdoc} + */ + public function set($key, $value, $ttl = null) + { + if ($this->serializer === null) { + $value = serialize($value); + } elseif ($this->serializer !== false) { + $value = call_user_func($this->serializer[0], $value); + } + $key = $this->normalizeKey($key); + $ttl = $this->normalizeTtl($ttl); + return $this->setValue($key, $value, $ttl); + } + + /** + * {@inheritdoc} + */ + public function setMultiple($values, $ttl = null) + { + $data = []; + foreach ($values as $key => $value) { + if ($this->serializer === null) { + $value = serialize($value); + } elseif ($this->serializer !== false) { + $value = call_user_func($this->serializer[0], $value); + } + $key = $this->normalizeKey($key); + $data[$key] = $value; + } + return $this->setValues($data, $this->normalizeTtl($ttl)); + } + + /** + * {@inheritdoc} + */ + public function delete($key) + { + $key = $this->normalizeKey($key); + return $this->deleteValue($key); + } + + /** + * {@inheritdoc} + */ + public function deleteMultiple($keys) + { + $result = true; + foreach ($keys as $key) { + if (!$this->delete($key)) { + $result = false; + } + } + return $result; + } + + /** + * Builds a normalized cache key from a given key. + * + * The given key will be type-casted to string. + * If the result string does not contain alphanumeric characters only or has more than 32 characters, + * then the hash of the key will be used. + * The result key will be returned back prefixed with [[keyPrefix]]. + * + * @param mixed $key the key to be normalized + * @return string the generated cache key + */ + protected function normalizeKey($key) + { + $key = (string)$key; + $key = ctype_alnum($key) && StringHelper::byteLength($key) <= 32 ? $key : md5($key); + return $this->keyPrefix . $key; + } + + /** + * Normalizes cache TTL handling `null` value and [[\DateInterval]] objects. + * @param int|\DateInterval $ttl raw TTL. + * @return int TTL value as UNIX timestamp. + */ + protected function normalizeTtl($ttl) + { + if ($ttl === null) { + return $this->defaultTtl; + } + if ($ttl instanceof \DateInterval) { + return (new \DateTime('@0'))->add($ttl)->getTimestamp(); + } + return (int)$ttl; + } + + /** + * Retrieves a value from cache with a specified key. + * This method should be implemented by child classes to retrieve the data + * from specific cache storage. + * @param string $key a unique key identifying the cached value + * @return mixed|false the value stored in cache, `false` if the value is not in the cache or expired. Most often + * value is a string. If you have disabled [[serializer]], it could be something else. + */ + abstract protected function getValue($key); + + /** + * Stores a value identified by a key in cache. + * This method should be implemented by child classes to store the data + * in specific cache storage. + * @param string $key the key identifying the value to be cached + * @param mixed $value the value to be cached. Most often it's a string. If you have disabled [[serializer]], + * it could be something else. + * @param int $ttl the number of seconds in which the cached value will expire. + * @return bool true if the value is successfully stored into cache, false otherwise + */ + abstract protected function setValue($key, $value, $ttl); + + /** + * Deletes a value with the specified key from cache + * This method should be implemented by child classes to delete the data from actual cache storage. + * @param string $key the key of the value to be deleted + * @return bool if no error happens during deletion + */ + abstract protected function deleteValue($key); + + /** + * Retrieves multiple values from cache with the specified keys. + * The default implementation calls [[getValue()]] multiple times to retrieve + * the cached values one by one. If the underlying cache storage supports multiget, + * this method should be overridden to exploit that feature. + * @param array $keys a list of keys identifying the cached values + * @return array a list of cached values indexed by the keys + */ + protected function getValues($keys) + { + $results = []; + foreach ($keys as $key) { + $value = $this->getValue($key); + if ($value !== false) { + $results[$key] = $value; + } + } + return $results; + } + + /** + * Stores multiple key-value pairs in cache. + * The default implementation calls [[setValue()]] multiple times store values one by one. If the underlying cache + * storage supports multi-set, this method should be overridden to exploit that feature. + * @param array $values array where key corresponds to cache key while value is the value stored + * @param int $ttl the number of seconds in which the cached values will expire. + * @return bool `true` on success and `false` on failure. + */ + protected function setValues($values, $ttl) + { + $result = true; + foreach ($values as $key => $value) { + if ($this->setValue($key, $value, $ttl) === false) { + $result = false; + } + } + return $result; + } +} \ No newline at end of file diff --git a/framework/caching/TagDependency.php b/framework/caching/TagDependency.php index 26b286c08ff..e42c01f2326 100644 --- a/framework/caching/TagDependency.php +++ b/framework/caching/TagDependency.php @@ -68,21 +68,21 @@ public function isChanged($cache) /** * Invalidates all of the cached data items that are associated with any of the specified [[tags]]. - * @param CacheInterface $cache the cache component that caches the data items + * @param \Psr\SimpleCache\CacheInterface $cache the cache component that caches the data items * @param string|array $tags */ public static function invalidate($cache, $tags) { $keys = []; foreach ((array) $tags as $tag) { - $keys[] = $cache->buildKey([__CLASS__, $tag]); + $keys[] = static::buildCacheKey($tag); } static::touchKeys($cache, $keys); } /** * Generates the timestamp for the specified cache keys. - * @param CacheInterface $cache + * @param \Psr\SimpleCache\CacheInterface $cache * @param string[] $keys * @return array the timestamp indexed by cache keys */ @@ -93,13 +93,13 @@ protected static function touchKeys($cache, $keys) foreach ($keys as $key) { $items[$key] = $time; } - $cache->multiSet($items); + $cache->setMultiple($items); return $items; } /** * Returns the timestamps for the specified tags. - * @param CacheInterface $cache + * @param \Psr\SimpleCache\CacheInterface $cache * @param string[] $tags * @return array the timestamps indexed by the specified tags. */ @@ -111,9 +111,21 @@ protected function getTimestamps($cache, $tags) $keys = []; foreach ($tags as $tag) { - $keys[] = $cache->buildKey([__CLASS__, $tag]); + $keys[] = static::buildCacheKey($tag); } - return $cache->multiGet($keys); + return $cache->getMultiple($keys); + } + + /** + * Builds a normalized cache key from a given tag, making sure it is short enough and safe + * for any particular cache storage. + * @param string $tag tag name. + * @return string cache key. + * @since 2.1.0 + */ + protected static function buildCacheKey($tag) + { + return md5(json_encode([__CLASS__, $tag])); } } diff --git a/framework/caching/WinCache.php b/framework/caching/WinCache.php index 3201311b15a..2d15e438b07 100644 --- a/framework/caching/WinCache.php +++ b/framework/caching/WinCache.php @@ -13,37 +13,42 @@ * To use this application component, the [WinCache PHP extension](http://www.iis.net/expand/wincacheforphp) * must be loaded. Also note that "wincache.ucenabled" should be set to "On" in your php.ini file. * - * See [[Cache]] manual for common cache operations that are supported by WinCache. + * Application configuration example: + * + * ```php + * return [ + * 'components' => [ + * 'cache' => [ + * 'class' => yii\caching\Cache::class, + * 'handler' => [ + * 'class' => yii\caching\WinCache::class, + * ], + * ], + * // ... + * ], + * // ... + * ]; + * ``` + * + * See [[\Psr\SimpleCache\CacheInterface]] for common cache operations that are supported by WinCache. * * For more details and usage information on Cache, see the [guide article on caching](guide:caching-overview). * * @author Qiang Xue * @since 2.0 */ -class WinCache extends Cache +class WinCache extends SimpleCache { /** - * Checks whether a specified key exists in the cache. - * This can be faster than getting the value from the cache if the data is big. - * Note that this method does not check whether the dependency associated - * with the cached data, if there is any, has changed. So a call to [[get]] - * may return false while exists returns true. - * @param mixed $key a key identifying the cached value. This can be a simple string or - * a complex data structure consisting of factors representing the key. - * @return bool true if a value exists in cache, false if the value is not in the cache or expired. + * {@inheritdoc} */ - public function exists($key) + public function has($key) { - $key = $this->buildKey($key); - - return wincache_ucache_exists($key); + return wincache_ucache_exists($this->normalizeKey($key)); } /** - * Retrieves a value from cache with a specified key. - * This is the implementation of the method declared in the parent class. - * @param string $key a unique key identifying the cached value - * @return string|bool the value stored in cache, false if the value is not in the cache or expired. + * {@inheritdoc} */ protected function getValue($key) { @@ -51,9 +56,7 @@ protected function getValue($key) } /** - * Retrieves multiple values from cache with the specified keys. - * @param array $keys a list of keys identifying the cached values - * @return array a list of cached values indexed by the keys + * {@inheritdoc} */ protected function getValues($keys) { @@ -61,64 +64,23 @@ protected function getValues($keys) } /** - * Stores a value identified by a key in cache. - * This is the implementation of the method declared in the parent class. - * - * @param string $key the key identifying the value to be cached - * @param mixed $value the value to be cached. Most often it's a string. If you have disabled [[serializer]], - * it could be something else. - * @param int $duration the number of seconds in which the cached value will expire. 0 means never expire. - * @return bool true if the value is successfully stored into cache, false otherwise - */ - protected function setValue($key, $value, $duration) - { - return wincache_ucache_set($key, $value, $duration); - } - - /** - * Stores multiple key-value pairs in cache. - * @param array $data array where key corresponds to cache key while value is the value stored - * @param int $duration the number of seconds in which the cached values will expire. 0 means never expire. - * @return array array of failed keys - */ - protected function setValues($data, $duration) - { - return wincache_ucache_set($data, null, $duration); - } - - /** - * Stores a value identified by a key into cache if the cache does not contain this key. - * This is the implementation of the method declared in the parent class. - * - * @param string $key the key identifying the value to be cached - * @param mixed $value the value to be cached. Most often it's a string. If you have disabled [[serializer]], - * it could be something else. - * @param int $duration the number of seconds in which the cached value will expire. 0 means never expire. - * @return bool true if the value is successfully stored into cache, false otherwise + * {@inheritdoc} */ - protected function addValue($key, $value, $duration) + protected function setValue($key, $value, $ttl) { - return wincache_ucache_add($key, $value, $duration); + return wincache_ucache_set($key, $value, $ttl); } /** - * Adds multiple key-value pairs to cache. - * The default implementation calls [[addValue()]] multiple times add values one by one. If the underlying cache - * storage supports multiadd, this method should be overridden to exploit that feature. - * @param array $data array where key corresponds to cache key while value is the value stored - * @param int $duration the number of seconds in which the cached values will expire. 0 means never expire. - * @return array array of failed keys + * {@inheritdoc} */ - protected function addValues($data, $duration) + protected function setValues($values, $ttl) { - return wincache_ucache_add($data, null, $duration); + return wincache_ucache_set($values, null, $ttl); } /** - * Deletes a value with the specified key from cache - * This is the implementation of the method declared in the parent class. - * @param string $key the key of the value to be deleted - * @return bool if no error happens during deletion + * {@inheritdoc} */ protected function deleteValue($key) { @@ -126,11 +88,9 @@ protected function deleteValue($key) } /** - * Deletes all values from cache. - * This is the implementation of the method declared in the parent class. - * @return bool whether the flush operation was successful. + * {@inheritdoc} */ - protected function flushValues() + public function clear() { return wincache_ucache_clear(); } diff --git a/framework/caching/ZendDataCache.php b/framework/caching/ZendDataCache.php index 4c5ae9061ca..8cfebf6832f 100644 --- a/framework/caching/ZendDataCache.php +++ b/framework/caching/ZendDataCache.php @@ -13,63 +13,51 @@ * To use this application component, the [Zend Data Cache PHP extension](http://www.zend.com/en/products/server/) * must be loaded. * - * See [[Cache]] for common cache operations that ZendDataCache supports. + * Application configuration example: + * + * ```php + * return [ + * 'components' => [ + * 'cache' => [ + * 'class' => yii\caching\Cache::class, + * 'handler' => [ + * 'class' => yii\caching\ZendDataCache::class, + * ], + * ], + * // ... + * ], + * // ... + * ]; + * ``` + * + * See [[\Psr\SimpleCache\CacheInterface]] for common cache operations that ZendDataCache supports. * * For more details and usage information on Cache, see the [guide article on caching](guide:caching-overview). * * @author Qiang Xue * @since 2.0 */ -class ZendDataCache extends Cache +class ZendDataCache extends SimpleCache { /** - * Retrieves a value from cache with a specified key. - * This is the implementation of the method declared in the parent class. - * @param string $key a unique key identifying the cached value - * @return mixed|false the value stored in cache, false if the value is not in the cache or expired. + * {@inheritdoc} */ protected function getValue($key) { $result = zend_shm_cache_fetch($key); - return $result === null ? false : $result; } /** - * Stores a value identified by a key in cache. - * This is the implementation of the method declared in the parent class. - * - * @param string $key the key identifying the value to be cached - * @param mixed $value the value to be cached. Most often it's a string. If you have disabled [[serializer]], - * it could be something else. - * @param int $duration the number of seconds in which the cached value will expire. 0 means never expire. - * @return bool true if the value is successfully stored into cache, false otherwise - */ - protected function setValue($key, $value, $duration) - { - return zend_shm_cache_store($key, $value, $duration); - } - - /** - * Stores a value identified by a key into cache if the cache does not contain this key. - * This is the implementation of the method declared in the parent class. - * - * @param string $key the key identifying the value to be cached - * @param mixed $value the value to be cached. Most often it's a string. If you have disabled [[serializer]], - * it could be something else. - * @param int $duration the number of seconds in which the cached value will expire. 0 means never expire. - * @return bool true if the value is successfully stored into cache, false otherwise + * {@inheritdoc} */ - protected function addValue($key, $value, $duration) + protected function setValue($key, $value, $ttl) { - return zend_shm_cache_fetch($key) === null ? $this->setValue($key, $value, $duration) : false; + return zend_shm_cache_store($key, $value, $ttl); } /** - * Deletes a value with the specified key from cache - * This is the implementation of the method declared in the parent class. - * @param string $key the key of the value to be deleted - * @return bool if no error happens during deletion + * {@inheritdoc} */ protected function deleteValue($key) { @@ -77,11 +65,9 @@ protected function deleteValue($key) } /** - * Deletes all values from cache. - * This is the implementation of the method declared in the parent class. - * @return bool whether the flush operation was successful. + * {@inheritdoc} */ - protected function flushValues() + public function clear() { return zend_shm_cache_clear(); } diff --git a/framework/composer.json b/framework/composer.json index 861c42e18cd..4dab44a047e 100644 --- a/framework/composer.json +++ b/framework/composer.json @@ -68,6 +68,7 @@ "ext-ctype": "*", "lib-pcre": "*", "yiisoft/yii2-composer": "~2.0.4", + "psr/simple-cache": "~1.0.0", "ezyang/htmlpurifier": "~4.6", "cebe/markdown": "~1.0.0 | ~1.1.0", "bower-asset/jquery": "2.2.*@stable | 2.1.*@stable | 1.11.*@stable | 1.12.*@stable", diff --git a/framework/console/controllers/CacheController.php b/framework/console/controllers/CacheController.php index 0cfa4e90c02..1e24050d2fd 100644 --- a/framework/console/controllers/CacheController.php +++ b/framework/console/controllers/CacheController.php @@ -7,35 +7,36 @@ namespace yii\console\controllers; +use Psr\SimpleCache\CacheInterface; use Yii; use yii\caching\ApcCache; -use yii\caching\CacheInterface; +use yii\caching\Cache; use yii\console\Controller; use yii\console\Exception; use yii\console\ExitCode; use yii\helpers\Console; /** - * Allows you to flush cache. + * Allows you to clear cache. * - * see list of available components to flush: + * see list of available components to clear: * * yii cache * - * flush particular components specified by their names: + * clear particular components specified by their names: * - * yii cache/flush first second third + * yii cache/clear first second third * - * flush all cache components that can be found in the system + * clear all cache components that can be found in the system * - * yii cache/flush-all + * yii cache/clear-all * * Note that the command uses cache components defined in your console application configuration file. If components * configured are different from web application, web application cache won't be cleared. In order to fix it please * duplicate web application cache components in console config. You can use any component names. * - * APC is not shared between PHP processes so flushing cache from command line has no effect on web. - * Flushing web cache could be either done by: + * APC is not shared between PHP processes so clearing cache from command line has no effect on web. + * Clearing web cache could be either done by: * * - Putting a php file under web root and calling it via HTTP * - Using [Cachetool](http://gordalina.github.io/cachetool/) @@ -47,29 +48,29 @@ class CacheController extends Controller { /** - * Lists the caches that can be flushed. + * Lists the caches that can be cleared. */ public function actionIndex() { $caches = $this->findCaches(); if (!empty($caches)) { - $this->notifyCachesCanBeFlushed($caches); + $this->notifyCachesCanBeCleared($caches); } else { $this->notifyNoCachesFound(); } } /** - * Flushes given cache components. + * Clears given cache components. * For example, * * ``` - * # flushes caches specified by their id: "first", "second", "third" - * yii cache/flush first second third + * # clears caches specified by their id: "first", "second", "third" + * yii cache/clear first second third * ``` */ - public function actionFlush() + public function actionClear() { $cachesInput = func_get_args(); @@ -92,7 +93,7 @@ public function actionFlush() return ExitCode::OK; } - if (!$this->confirmFlush($foundCaches)) { + if (!$this->confirmClear($foundCaches)) { return ExitCode::OK; } @@ -100,17 +101,17 @@ public function actionFlush() $cachesInfo[] = [ 'name' => $name, 'class' => $class, - 'is_flushed' => $this->canBeFlushed($class) ? Yii::$app->get($name)->flush() : false, + 'is_cleared' => $this->canBeCleared($class) ? Yii::$app->get($name)->clear() : false, ]; } - $this->notifyFlushed($cachesInfo); + $this->notifyCleared($cachesInfo); } /** - * Flushes all caches registered in the system. + * Clears all caches registered in the system. */ - public function actionFlushAll() + public function actionClearAll() { $caches = $this->findCaches(); $cachesInfo = []; @@ -124,11 +125,11 @@ public function actionFlushAll() $cachesInfo[] = [ 'name' => $name, 'class' => $class, - 'is_flushed' => $this->canBeFlushed($class) ? Yii::$app->get($name)->flush() : false, + 'is_cleared' => $this->canBeCleared($class) ? Yii::$app->get($name)->clear() : false, ]; } - $this->notifyFlushed($cachesInfo); + $this->notifyCleared($cachesInfo); } /** @@ -136,7 +137,7 @@ public function actionFlushAll() * * ``` * # clears cache schema specified by component id: "db" - * yii cache/flush-schema db + * yii cache/clear-schema db * ``` * * @param string $db id connection component @@ -146,7 +147,7 @@ public function actionFlushAll() * * @since 2.0.1 */ - public function actionFlushSchema($db = 'db') + public function actionClearSchema($db = 'db') { $connection = Yii::$app->get($db, false); if ($connection === null) { @@ -157,32 +158,32 @@ public function actionFlushSchema($db = 'db') if (!$connection instanceof \yii\db\Connection) { $this->stdout("\"$db\" component doesn't inherit \\yii\\db\\Connection.\n", Console::FG_RED); return ExitCode::UNSPECIFIED_ERROR; - } elseif (!$this->confirm("Flush cache schema for \"$db\" connection?")) { + } elseif (!$this->confirm("Clear cache schema for \"$db\" connection?")) { return ExitCode::OK; } try { $schema = $connection->getSchema(); $schema->refresh(); - $this->stdout("Schema cache for component \"$db\", was flushed.\n\n", Console::FG_GREEN); + $this->stdout("Schema cache for component \"$db\", was cleared.\n\n", Console::FG_GREEN); } catch (\Exception $e) { $this->stdout($e->getMessage() . "\n\n", Console::FG_RED); } } /** - * Notifies user that given caches are found and can be flushed. + * Notifies user that given caches are found and can be cleared. * @param array $caches array of cache component classes */ - private function notifyCachesCanBeFlushed($caches) + private function notifyCachesCanBeCleared($caches) { $this->stdout("The following caches were found in the system:\n\n", Console::FG_YELLOW); foreach ($caches as $name => $class) { - if ($this->canBeFlushed($class)) { + if ($this->canBeCleared($class)) { $this->stdout("\t* $name ($class)\n", Console::FG_GREEN); } else { - $this->stdout("\t* $name ($class) - can not be flushed via console\n", Console::FG_YELLOW); + $this->stdout("\t* $name ($class) - can not be cleared via console\n", Console::FG_YELLOW); } } @@ -215,15 +216,15 @@ private function notifyNotFoundCaches($cachesNames) /** * @param array $caches */ - private function notifyFlushed($caches) + private function notifyCleared($caches) { $this->stdout("The following cache components were processed:\n\n", Console::FG_YELLOW); foreach ($caches as $cache) { $this->stdout("\t* " . $cache['name'] . ' (' . $cache['class'] . ')', Console::FG_GREEN); - if (!$cache['is_flushed']) { - $this->stdout(" - not flushed\n", Console::FG_RED); + if (!$cache['is_cleared']) { + $this->stdout(" - not cleared\n", Console::FG_RED); } else { $this->stdout("\n"); } @@ -233,19 +234,19 @@ private function notifyFlushed($caches) } /** - * Prompts user with confirmation if caches should be flushed. + * Prompts user with confirmation if caches should be cleared. * @param array $cachesNames * @return bool */ - private function confirmFlush($cachesNames) + private function confirmClear($cachesNames) { - $this->stdout("The following cache components will be flushed:\n\n", Console::FG_YELLOW); + $this->stdout("The following cache components will be cleared:\n\n", Console::FG_YELLOW); foreach ($cachesNames as $name) { $this->stdout("\t* $name \n", Console::FG_GREEN); } - return $this->confirm("\nFlush above cache components?"); + return $this->confirm("\nClear above cache components?"); } /** @@ -287,11 +288,11 @@ private function isCacheClass($className) } /** - * Checks if cache of a certain class can be flushed + * Checks if cache of a certain class can be cleared * @param string $className class name. * @return bool */ - private function canBeFlushed($className) + private function canBeCleared($className) { return !is_a($className, ApcCache::class, true) || php_sapi_name() !== 'cli'; } diff --git a/framework/web/CacheSession.php b/framework/web/CacheSession.php index 054f6a0b43f..2289eaf194d 100644 --- a/framework/web/CacheSession.php +++ b/framework/web/CacheSession.php @@ -79,7 +79,7 @@ public function readSession($id) { $data = $this->cache->get($this->calculateKey($id)); - return $data === false ? '' : $data; + return $data === null ? '' : $data; } /** @@ -103,7 +103,7 @@ public function writeSession($id, $data) public function destroySession($id) { $cacheId = $this->calculateKey($id); - if ($this->cache->exists($cacheId) === false) { + if ($this->cache->has($cacheId) === false) { return true; } diff --git a/tests/framework/base/ViewTest.php b/tests/framework/base/ViewTest.php index c9d7c762e81..6ba0eaa19ce 100644 --- a/tests/framework/base/ViewTest.php +++ b/tests/framework/base/ViewTest.php @@ -9,6 +9,7 @@ use Yii; use yii\base\View; +use yii\caching\Cache; use yii\caching\FileCache; use yii\helpers\FileHelper; use yiiunit\TestCase; @@ -71,14 +72,14 @@ public function testExceptionOnRenderFile() public function testRenderDynamic() { - Yii::$app->set('cache', new FileCache(['cachePath' => '@yiiunit/runtime/cache'])); + Yii::$app->set('cache', new Cache(['handler' => new FileCache(['cachePath' => '@yiiunit/runtime/cache'])])); $view = new View(); $this->assertEquals(1, $view->renderDynamic('return 1;')); } public function testRenderDynamic_DynamicPlaceholders() { - Yii::$app->set('cache', new FileCache(['cachePath' => '@yiiunit/runtime/cache'])); + Yii::$app->set('cache', new Cache(['handler' => new FileCache(['cachePath' => '@yiiunit/runtime/cache'])])); $statement = "return 1;"; $view = new View(); if ($view->beginCache(__FUNCTION__, ['duration' => 3])) { diff --git a/tests/framework/caching/ApcCacheTest.php b/tests/framework/caching/ApcCacheTest.php index 2f31737eae0..8515b9bca08 100644 --- a/tests/framework/caching/ApcCacheTest.php +++ b/tests/framework/caching/ApcCacheTest.php @@ -8,6 +8,7 @@ namespace yiiunit\framework\caching; use yii\caching\ApcCache; +use yii\caching\Cache; /** * Class for testing APC cache backend @@ -19,7 +20,7 @@ class ApcCacheTest extends CacheTestCase private $_cacheInstance = null; /** - * @return ApcCache + * @return Cache */ protected function getCacheInstance() { @@ -32,7 +33,9 @@ protected function getCacheInstance() } if ($this->_cacheInstance === null) { - $this->_cacheInstance = new ApcCache(); + $this->_cacheInstance = new Cache([ + 'handler' => new ApcCache() + ]); } return $this->_cacheInstance; diff --git a/tests/framework/caching/ArrayCacheTest.php b/tests/framework/caching/ArrayCacheTest.php index e6359e5b367..39186b47ef2 100644 --- a/tests/framework/caching/ArrayCacheTest.php +++ b/tests/framework/caching/ArrayCacheTest.php @@ -8,6 +8,7 @@ namespace yiiunit\framework\caching; use yii\caching\ArrayCache; +use yii\caching\Cache; /** * Class for testing file cache backend @@ -18,12 +19,14 @@ class ArrayCacheTest extends CacheTestCase private $_cacheInstance = null; /** - * @return ArrayCache + * @return Cache */ protected function getCacheInstance() { if ($this->_cacheInstance === null) { - $this->_cacheInstance = new ArrayCache(); + $this->_cacheInstance = new Cache([ + 'handler' => new ArrayCache() + ]); } return $this->_cacheInstance; } @@ -37,7 +40,7 @@ public function testExpire() static::$microtime++; $this->assertEquals('expire_test', $cache->get('expire_test')); static::$microtime++; - $this->assertFalse($cache->get('expire_test')); + $this->assertNull($cache->get('expire_test')); } public function testExpireAdd() @@ -49,6 +52,6 @@ public function testExpireAdd() static::$microtime++; $this->assertEquals('expire_testa', $cache->get('expire_testa')); static::$microtime++; - $this->assertFalse($cache->get('expire_testa')); + $this->assertNull($cache->get('expire_testa')); } } diff --git a/tests/framework/caching/CacheTestCase.php b/tests/framework/caching/CacheTestCase.php index 71a29f69646..99f08fc474d 100644 --- a/tests/framework/caching/CacheTestCase.php +++ b/tests/framework/caching/CacheTestCase.php @@ -73,7 +73,7 @@ public function prepare() { $cache = $this->getCacheInstance(); - $cache->flush(); + $cache->clear(); $cache->set('string_test', 'string_test'); $cache->set('number_test', 42); $cache->set('array_test', ['array_test' => 'array_test']); @@ -107,20 +107,20 @@ public function testGet() /** * @return array testing multiSet with and without expiry */ - public function multiSetExpiry() + public function dataProviderSetMultiple() { return [[0], [2]]; } /** - * @dataProvider multiSetExpiry + * @dataProvider dataProviderSetMultiple */ - public function testMultiset($expiry) + public function testSetMultiple($expiry) { $cache = $this->getCacheInstance(); - $cache->flush(); + $cache->clear(); - $cache->multiSet([ + $cache->setMultiple([ 'string_test' => 'string_test', 'number_test' => 42, 'array_test' => ['array_test' => 'array_test'], @@ -135,16 +135,16 @@ public function testMultiset($expiry) $this->assertEquals('array_test', $array['array_test']); } - public function testExists() + public function testHas() { $cache = $this->prepare(); - $this->assertTrue($cache->exists('string_test')); + $this->assertTrue($cache->has('string_test')); // check whether exists affects the value $this->assertEquals('string_test', $cache->get('string_test')); - $this->assertTrue($cache->exists('number_test')); - $this->assertFalse($cache->exists('not_exists')); + $this->assertTrue($cache->has('number_test')); + $this->assertFalse($cache->has('not_exists')); } public function testArrayAccess() @@ -159,7 +159,7 @@ public function testGetNonExistent() { $cache = $this->getCacheInstance(); - $this->assertFalse($cache->get('non_existent_key')); + $this->assertNull($cache->get('non_existent_key')); } public function testStoreSpecialValues() @@ -173,21 +173,21 @@ public function testStoreSpecialValues() $this->assertTrue($cache->get('bool_value')); } - public function testMultiGet() + public function testGetMultiple() { $cache = $this->prepare(); - $this->assertEquals(['string_test' => 'string_test', 'number_test' => 42], $cache->multiGet(['string_test', 'number_test'])); + $this->assertEquals(['string_test' => 'string_test', 'number_test' => 42], $cache->getMultiple(['string_test', 'number_test'])); // ensure that order does not matter - $this->assertEquals(['number_test' => 42, 'string_test' => 'string_test'], $cache->multiGet(['number_test', 'string_test'])); - $this->assertEquals(['number_test' => 42, 'non_existent_key' => null], $cache->multiGet(['number_test', 'non_existent_key'])); + $this->assertEquals(['number_test' => 42, 'string_test' => 'string_test'], $cache->getMultiple(['number_test', 'string_test'])); + $this->assertEquals(['number_test' => 42, 'non_existent_key' => null], $cache->getMultiple(['number_test', 'non_existent_key'])); } public function testDefaultTtl() { $cache = $this->getCacheInstance(); - $this->assertSame(0, $cache->defaultDuration); + $this->assertSame(0, $cache->handler->defaultTtl); } public function testExpire() @@ -198,7 +198,7 @@ public function testExpire() usleep(500000); $this->assertEquals('expire_test', $cache->get('expire_test')); usleep(2500000); - $this->assertFalse($cache->get('expire_test')); + $this->assertNull($cache->get('expire_test')); } public function testExpireAdd() @@ -209,7 +209,7 @@ public function testExpireAdd() usleep(500000); $this->assertEquals('expire_testa', $cache->get('expire_testa')); usleep(2500000); - $this->assertFalse($cache->get('expire_testa')); + $this->assertNull($cache->get('expire_testa')); } public function testAdd() @@ -221,18 +221,18 @@ public function testAdd() $this->assertEquals(42, $cache->get('number_test')); // should store data if it's not there yet - $this->assertFalse($cache->get('add_test')); + $this->assertNull($cache->get('add_test')); $this->assertTrue($cache->add('add_test', 13)); $this->assertEquals(13, $cache->get('add_test')); } - public function testMultiAdd() + public function testAddMultiple() { $cache = $this->prepare(); - $this->assertFalse($cache->get('add_test')); + $this->assertNull($cache->get('add_test')); - $cache->multiAdd([ + $cache->addMultiple([ 'number_test' => 13, 'add_test' => 13, ]); @@ -247,14 +247,14 @@ public function testDelete() $this->assertNotNull($cache->get('number_test')); $this->assertTrue($cache->delete('number_test')); - $this->assertFalse($cache->get('number_test')); + $this->assertNull($cache->get('number_test')); } public function testFlush() { $cache = $this->prepare(); - $this->assertTrue($cache->flush()); - $this->assertFalse($cache->get('number_test')); + $this->assertTrue($cache->clear()); + $this->assertNull($cache->get('number_test')); } public function testGetOrSet() diff --git a/tests/framework/caching/DbCacheTest.php b/tests/framework/caching/DbCacheTest.php index 557701c03ab..8efee0e53c9 100644 --- a/tests/framework/caching/DbCacheTest.php +++ b/tests/framework/caching/DbCacheTest.php @@ -7,6 +7,7 @@ namespace yiiunit\framework\caching; +use yii\caching\Cache; use yii\caching\DbCache; /** @@ -38,6 +39,12 @@ protected function setUp() ')->execute(); } + protected function tearDown() + { + $this->getConnection()->createCommand('DROP TABLE IF EXISTS cache')->execute(); + parent::tearDown(); + } + /** * @param bool $reset whether to clean up the test database * @return \yii\db\Connection @@ -67,12 +74,14 @@ public function getConnection($reset = true) } /** - * @return DbCache + * @return Cache */ protected function getCacheInstance() { if ($this->_cacheInstance === null) { - $this->_cacheInstance = new DbCache(['db' => $this->getConnection()]); + $this->_cacheInstance = new Cache([ + 'handler' => new DbCache(['db' => $this->getConnection()]) + ]); } return $this->_cacheInstance; @@ -87,7 +96,7 @@ public function testExpire() static::$time++; $this->assertEquals('expire_test', $cache->get('expire_test')); static::$time++; - $this->assertFalse($cache->get('expire_test')); + $this->assertNull($cache->get('expire_test')); } public function testExpireAdd() @@ -99,6 +108,6 @@ public function testExpireAdd() static::$time++; $this->assertEquals('expire_testa', $cache->get('expire_testa')); static::$time++; - $this->assertFalse($cache->get('expire_testa')); + $this->assertNull($cache->get('expire_testa')); } } diff --git a/tests/framework/caching/DependencyTest.php b/tests/framework/caching/DependencyTest.php index a31b1bff4af..3c8b239b773 100644 --- a/tests/framework/caching/DependencyTest.php +++ b/tests/framework/caching/DependencyTest.php @@ -9,6 +9,7 @@ use yii\caching\Cache; use yii\caching\Dependency; +use yii\caching\SimpleCache; use yiiunit\data\cache\MockDependency; use yiiunit\TestCase; @@ -44,8 +45,10 @@ public function testGenerateReusableHash() public function testIsChanged() { + /* @var $dependency Dependency */ + /* @var $cache SimpleCache */ $dependency = $this->getMockForAbstractClass(Dependency::class); - $cache = $this->getMockForAbstractClass(Cache::class); + $cache = $this->getMockForAbstractClass(SimpleCache::class); $result = $dependency->isChanged($cache); $this->assertFalse($result); diff --git a/tests/framework/caching/FileCacheTest.php b/tests/framework/caching/FileCacheTest.php index 7129c880bfd..ce68a0aa699 100644 --- a/tests/framework/caching/FileCacheTest.php +++ b/tests/framework/caching/FileCacheTest.php @@ -7,6 +7,7 @@ namespace yiiunit\framework\caching; +use yii\caching\Cache; use yii\caching\FileCache; /** @@ -18,12 +19,14 @@ class FileCacheTest extends CacheTestCase private $_cacheInstance = null; /** - * @return FileCache + * @return Cache */ protected function getCacheInstance() { if ($this->_cacheInstance === null) { - $this->_cacheInstance = new FileCache(['cachePath' => '@yiiunit/runtime/cache']); + $this->_cacheInstance = new Cache([ + 'handler' => new FileCache(['cachePath' => '@yiiunit/runtime/cache']) + ]); } return $this->_cacheInstance; @@ -38,7 +41,7 @@ public function testExpire() static::$time++; $this->assertEquals('expire_test', $cache->get('expire_test')); static::$time++; - $this->assertFalse($cache->get('expire_test')); + $this->assertNull($cache->get('expire_test')); } public function testExpireAdd() @@ -50,6 +53,6 @@ public function testExpireAdd() static::$time++; $this->assertEquals('expire_testa', $cache->get('expire_testa')); static::$time++; - $this->assertFalse($cache->get('expire_testa')); + $this->assertNull($cache->get('expire_testa')); } } diff --git a/tests/framework/caching/MemCachedTest.php b/tests/framework/caching/MemCachedTest.php index ab55f10994b..1c0b5ece7a0 100644 --- a/tests/framework/caching/MemCachedTest.php +++ b/tests/framework/caching/MemCachedTest.php @@ -7,6 +7,7 @@ namespace yiiunit\framework\caching; +use yii\caching\Cache; use yii\caching\MemCached; /** @@ -19,7 +20,7 @@ class MemCachedTest extends CacheTestCase private $_cacheInstance = null; /** - * @return MemCached + * @return Cache */ protected function getCacheInstance() { @@ -33,7 +34,9 @@ protected function getCacheInstance() } if ($this->_cacheInstance === null) { - $this->_cacheInstance = new MemCached(); + $this->_cacheInstance = new Cache([ + 'handler' => new MemCached() + ]); } return $this->_cacheInstance; diff --git a/tests/framework/caching/SimpleCacheTest.php b/tests/framework/caching/SimpleCacheTest.php new file mode 100644 index 00000000000..101cb4d2c2d --- /dev/null +++ b/tests/framework/caching/SimpleCacheTest.php @@ -0,0 +1,64 @@ +cache = $this->getMockBuilder(SimpleCache::class)->getMockForAbstractClass(); + } + + /** + * Data provider for [[testNormalizeTtl()]] + * @return array test data. + */ + public function dataProviderNormalizeTtl() + { + return [ + [123, 123], + ['123', 123], + [null, 9999], + [0, 0], + [new DateInterval('PT6H8M'), (6 * 3600 + 8 * 60)], + [new DateInterval('P2Y4D'), (2 * 365 * 24 * 3600 + 4 * 24 * 3600)], + ]; + } + + /** + * @dataProvider dataProviderNormalizeTtl + * + * @covers \yii\caching\SimpleCache::normalizeTtl() + * + * @param mixed $ttl + * @param int $expectedResult + */ + public function testNormalizeTtl($ttl, $expectedResult) + { + $this->cache->defaultTtl = 9999; + $this->assertEquals($expectedResult, $this->invokeMethod($this->cache, 'normalizeTtl', [$ttl])); + } +} \ No newline at end of file diff --git a/tests/framework/caching/TagDependencyTest.php b/tests/framework/caching/TagDependencyTest.php index b56c91b9955..bb2a74a3945 100644 --- a/tests/framework/caching/TagDependencyTest.php +++ b/tests/framework/caching/TagDependencyTest.php @@ -7,6 +7,7 @@ namespace yiiunit\framework\caching; +use yii\caching\Cache; use yii\caching\FileCache; use yii\caching\TagDependency; use yiiunit\TestCase; @@ -18,7 +19,7 @@ class TagDependencyTest extends TestCase { public function testInvalidate() { - $cache = new FileCache(['cachePath' => '@yiiunit/runtime/cache']); + $cache = new Cache(['handler' => new FileCache(['cachePath' => '@yiiunit/runtime/cache'])]); // single tag test $cache->set('a1', 11, 0, new TagDependency(['tags' => 't1'])); @@ -32,16 +33,16 @@ public function testInvalidate() $this->assertEquals(22, $cache->get('b2')); TagDependency::invalidate($cache, 't1'); - $this->assertFalse($cache->get('a1')); - $this->assertFalse($cache->get('a2')); + $this->assertNull($cache->get('a1')); + $this->assertNull($cache->get('a2')); $this->assertEquals(21, $cache->get('b1')); $this->assertEquals(22, $cache->get('b2')); TagDependency::invalidate($cache, 't2'); - $this->assertFalse($cache->get('a1')); - $this->assertFalse($cache->get('a2')); - $this->assertFalse($cache->get('b1')); - $this->assertFalse($cache->get('b2')); + $this->assertNull($cache->get('a1')); + $this->assertNull($cache->get('a2')); + $this->assertNull($cache->get('b1')); + $this->assertNull($cache->get('b2')); // multiple tag test $cache->set('a1', 11, 0, new TagDependency(['tags' => ['t1', 't2']])); @@ -55,16 +56,16 @@ public function testInvalidate() $this->assertEquals(22, $cache->get('b2')); TagDependency::invalidate($cache, 't1'); - $this->assertFalse($cache->get('a1')); - $this->assertFalse($cache->get('a2')); - $this->assertFalse($cache->get('b1')); + $this->assertNull($cache->get('a1')); + $this->assertNull($cache->get('a2')); + $this->assertNull($cache->get('b1')); $this->assertEquals(22, $cache->get('b2')); TagDependency::invalidate($cache, 't2'); - $this->assertFalse($cache->get('a1')); - $this->assertFalse($cache->get('a2')); - $this->assertFalse($cache->get('b1')); - $this->assertFalse($cache->get('b2')); + $this->assertNull($cache->get('a1')); + $this->assertNull($cache->get('a2')); + $this->assertNull($cache->get('b1')); + $this->assertNull($cache->get('b2')); $cache->set('a1', 11, 0, new TagDependency(['tags' => ['t1', 't2']])); $cache->set('a2', 12, 0, new TagDependency(['tags' => 't1'])); @@ -77,9 +78,9 @@ public function testInvalidate() $this->assertEquals(22, $cache->get('b2')); TagDependency::invalidate($cache, ['t1', 't2']); - $this->assertFalse($cache->get('a1')); - $this->assertFalse($cache->get('a2')); - $this->assertFalse($cache->get('b1')); - $this->assertFalse($cache->get('b2')); + $this->assertNull($cache->get('a1')); + $this->assertNull($cache->get('a2')); + $this->assertNull($cache->get('b1')); + $this->assertNull($cache->get('b2')); } } diff --git a/tests/framework/caching/WinCacheTest.php b/tests/framework/caching/WinCacheTest.php index e29069225d5..1f45a08afac 100644 --- a/tests/framework/caching/WinCacheTest.php +++ b/tests/framework/caching/WinCacheTest.php @@ -7,6 +7,7 @@ namespace yiiunit\framework\caching; +use yii\caching\Cache; use yii\caching\WinCache; /** @@ -19,7 +20,7 @@ class WinCacheTest extends CacheTestCase private $_cacheInstance = null; /** - * @return WinCache + * @return Cache */ protected function getCacheInstance() { @@ -32,7 +33,9 @@ protected function getCacheInstance() } if ($this->_cacheInstance === null) { - $this->_cacheInstance = new WinCache(); + $this->_cacheInstance = new Cache([ + 'handler' => new WinCache() + ]); } return $this->_cacheInstance; diff --git a/tests/framework/console/UnkownCommandExceptionTest.php b/tests/framework/console/UnkownCommandExceptionTest.php index 88897ede55a..32258f51ab1 100644 --- a/tests/framework/console/UnkownCommandExceptionTest.php +++ b/tests/framework/console/UnkownCommandExceptionTest.php @@ -38,10 +38,10 @@ public function suggestedCommandsProvider() ['mirgte/up', ['migrate/up']], ['mirgte', ['migrate']], ['hlp', ['help']], - ['ca', ['cache', 'cache/flush', 'cache/flush-all', 'cache/flush-schema', 'cache/index']], - ['cach', ['cache', 'cache/flush', 'cache/flush-all', 'cache/flush-schema', 'cache/index']], - ['cach/fush', ['cache/flush']], - ['cach/fushall', ['cache/flush-all']], + ['ca', ['cache', 'cache/clear', 'cache/clear-all', 'cache/clear-schema', 'cache/index']], + ['cach', ['cache', 'cache/clear', 'cache/clear-all', 'cache/clear-schema', 'cache/index']], + ['cach/clear', ['cache/clear']], + ['cach/clearall', ['cache/clear-all']], ['what?', []], // test UTF 8 chars ['ёлка', []], diff --git a/tests/framework/console/controllers/CacheControllerTest.php b/tests/framework/console/controllers/CacheControllerTest.php index 89496815cd5..ee8e5a144f2 100644 --- a/tests/framework/console/controllers/CacheControllerTest.php +++ b/tests/framework/console/controllers/CacheControllerTest.php @@ -50,7 +50,7 @@ protected function setUp() 'components' => [ 'firstCache' => 'yii\caching\ArrayCache', 'secondCache' => 'yii\caching\ArrayCache', - 'session' => 'yii\web\CacheSession', // should be ignored at `actionFlushAll()` + 'session' => 'yii\web\CacheSession', // should be ignored at `actionClearAll()` 'db' => [ 'class' => isset($config['class']) ? $config['class'] : 'yii\db\Connection', 'dsn' => $config['dsn'], @@ -79,10 +79,10 @@ public function testFlushOne() Yii::$app->firstCache->set('secondKey', 'secondValue'); Yii::$app->secondCache->set('thirdKey', 'thirdValue'); - $this->_cacheController->actionFlush('firstCache'); + $this->_cacheController->actionClear('firstCache'); - $this->assertFalse(Yii::$app->firstCache->get('firstKey'), 'first cache data should be flushed'); - $this->assertFalse(Yii::$app->firstCache->get('secondKey'), 'first cache data should be flushed'); + $this->assertNull(Yii::$app->firstCache->get('firstKey'), 'first cache data should be flushed'); + $this->assertNull(Yii::$app->firstCache->get('secondKey'), 'first cache data should be flushed'); $this->assertEquals('thirdValue', Yii::$app->secondCache->get('thirdKey'), 'second cache data should not be flushed'); } @@ -99,7 +99,7 @@ public function testClearSchema() $noCacheSchemas = $schema->getTableSchemas('', true); $this->assertNotEquals($noCacheSchemas, $cacheSchema, 'Schemas should be different.'); - $this->_cacheController->actionFlushSchema('db'); + $this->_cacheController->actionClearSchema('db'); $cacheSchema = $schema->getTableSchemas('', false); $this->assertEquals($noCacheSchemas, $cacheSchema, 'Schema cache should be flushed.'); } @@ -110,18 +110,18 @@ public function testFlushBoth() Yii::$app->firstCache->set('secondKey', 'secondValue'); Yii::$app->secondCache->set('thirdKey', 'secondValue'); - $this->_cacheController->actionFlush('firstCache', 'secondCache'); + $this->_cacheController->actionClear('firstCache', 'secondCache'); - $this->assertFalse(Yii::$app->firstCache->get('firstKey'), 'first cache data should be flushed'); - $this->assertFalse(Yii::$app->firstCache->get('secondKey'), 'first cache data should be flushed'); - $this->assertFalse(Yii::$app->secondCache->get('thirdKey'), 'second cache data should be flushed'); + $this->assertNull(Yii::$app->firstCache->get('firstKey'), 'first cache data should be flushed'); + $this->assertNull(Yii::$app->firstCache->get('secondKey'), 'first cache data should be flushed'); + $this->assertNull(Yii::$app->secondCache->get('thirdKey'), 'second cache data should be flushed'); } public function testNotFoundFlush() { Yii::$app->firstCache->set('firstKey', 'firstValue'); - $this->_cacheController->actionFlush('notExistingCache'); + $this->_cacheController->actionClear('notExistingCache'); $this->assertEquals('firstValue', Yii::$app->firstCache->get('firstKey'), 'first cache data should not be flushed'); } @@ -131,7 +131,7 @@ public function testNotFoundFlush() */ public function testNothingToFlushException() { - $this->_cacheController->actionFlush(); + $this->_cacheController->actionClear(); } public function testFlushAll() @@ -139,9 +139,9 @@ public function testFlushAll() Yii::$app->firstCache->set('firstKey', 'firstValue'); Yii::$app->secondCache->set('thirdKey', 'secondValue'); - $this->_cacheController->actionFlushAll(); + $this->_cacheController->actionClearAll(); - $this->assertFalse(Yii::$app->firstCache->get('firstKey'), 'first cache data should be flushed'); - $this->assertFalse(Yii::$app->secondCache->get('thirdKey'), 'second cache data should be flushed'); + $this->assertNull(Yii::$app->firstCache->get('firstKey'), 'first cache data should be flushed'); + $this->assertNull(Yii::$app->secondCache->get('thirdKey'), 'second cache data should be flushed'); } } diff --git a/tests/framework/console/controllers/HelpControllerTest.php b/tests/framework/console/controllers/HelpControllerTest.php index 708c069ee24..29825f96924 100644 --- a/tests/framework/console/controllers/HelpControllerTest.php +++ b/tests/framework/console/controllers/HelpControllerTest.php @@ -65,9 +65,9 @@ public function testActionList() $result = Console::stripAnsiFormat($this->runControllerAction('list')); $this->assertEqualsWithoutLE(<<<'STRING' cache -cache/flush -cache/flush-all -cache/flush-schema +cache/clear +cache/clear-all +cache/clear-schema cache/index help help/index diff --git a/tests/framework/db/CommandTest.php b/tests/framework/db/CommandTest.php index ae9d4ca2175..3ff8e1717ba 100644 --- a/tests/framework/db/CommandTest.php +++ b/tests/framework/db/CommandTest.php @@ -7,6 +7,8 @@ namespace yiiunit\framework\db; +use yii\caching\ArrayCache; +use yii\caching\Cache; use yii\caching\FileCache; use yii\db\Connection; use yii\db\DataReader; @@ -861,7 +863,7 @@ public function testQueryCache() { $db = $this->getConnection(); $db->enableQueryCache = true; - $db->queryCache = new FileCache(['cachePath' => '@yiiunit/runtime/cache']); + $db->queryCache = new Cache(['handler' => new ArrayCache()]); $command = $db->createCommand('SELECT [[name]] FROM {{customer}} WHERE [[id]] = :id'); $this->assertEquals('user1', $command->bindValue(':id', 1)->queryScalar()); diff --git a/tests/framework/filters/PageCacheTest.php b/tests/framework/filters/PageCacheTest.php index edf6b20486d..e5ad433d53a 100644 --- a/tests/framework/filters/PageCacheTest.php +++ b/tests/framework/filters/PageCacheTest.php @@ -10,6 +10,7 @@ use Yii; use yii\base\Action; use yii\caching\ArrayCache; +use yii\caching\Cache; use yii\caching\ExpressionDependency; use yii\filters\PageCache; use yii\helpers\ArrayHelper; @@ -153,7 +154,7 @@ public function testCache($testCase) $controller = new Controller('test', Yii::$app); $action = new Action('test', $controller); $filter = new PageCache(array_merge([ - 'cache' => $cache = new ArrayCache(), + 'cache' => $cache = new Cache(['handler' => new ArrayCache()]), 'view' => new View(), ], $testCase['properties'])); $this->assertTrue($filter->beforeAction($action), $testCase['name']); @@ -195,9 +196,9 @@ public function testCache($testCase) 'statusText' => Yii::$app->response->statusText, ]; if ($testCase['cacheable']) { - $this->assertNotEmpty($this->getInaccessibleProperty($filter->cache, '_cache'), $testCase['name']); + $this->assertNotEmpty($this->getInaccessibleProperty($filter->cache->handler, '_cache'), $testCase['name']); } else { - $this->assertEmpty($this->getInaccessibleProperty($filter->cache, '_cache'), $testCase['name']); + $this->assertEmpty($this->getInaccessibleProperty($filter->cache->handler, '_cache'), $testCase['name']); return; } @@ -251,7 +252,7 @@ public function testExpired() $controller = new Controller('test', Yii::$app); $action = new Action('test', $controller); $filter = new PageCache([ - 'cache' => $cache = new ArrayCache(), + 'cache' => $cache = new Cache(['handler' => new ArrayCache()]), 'view' => new View(), 'duration' => 1, ]); @@ -264,7 +265,7 @@ public function testExpired() Yii::$app->response->send(); ob_end_clean(); - $this->assertNotEmpty($this->getInaccessibleProperty($filter->cache, '_cache')); + $this->assertNotEmpty($this->getInaccessibleProperty($filter->cache->handler, '_cache')); // mock sleep(2); CacheTestCase::$time += 2; @@ -303,7 +304,7 @@ public function testVaryByRoute() $action = new Action('test', $controller); Yii::$app->requestedRoute = $action->uniqueId; $filter = new PageCache([ - 'cache' => $cache = new ArrayCache(), + 'cache' => $cache = new Cache(['handler' => new ArrayCache()]), 'view' => new View(), 'varyByRoute' => $enabled, ]); @@ -316,7 +317,7 @@ public function testVaryByRoute() Yii::$app->response->send(); ob_end_clean(); - $this->assertNotEmpty($this->getInaccessibleProperty($filter->cache, '_cache')); + $this->assertNotEmpty($this->getInaccessibleProperty($filter->cache->handler, '_cache')); // Verifies the cached response $this->destroyApplication(); @@ -356,7 +357,7 @@ public function testVariations() $originalVariations = $testCases[0]; array_shift($originalVariations); $filter = new PageCache([ - 'cache' => $cache = new ArrayCache(), + 'cache' => $cache = new Cache(['handler' => new ArrayCache()]), 'view' => new View(), 'variations' => $originalVariations, ]); @@ -369,7 +370,7 @@ public function testVariations() Yii::$app->response->send(); ob_end_clean(); - $this->assertNotEmpty($this->getInaccessibleProperty($filter->cache, '_cache')); + $this->assertNotEmpty($this->getInaccessibleProperty($filter->cache->handler, '_cache')); // Verifies the cached response $this->destroyApplication(); @@ -405,7 +406,7 @@ public function testDependency() $controller = new Controller('test', Yii::$app); $action = new Action('test', $controller); $filter = new PageCache([ - 'cache' => $cache = new ArrayCache(), + 'cache' => $cache = new Cache(['handler' => new ArrayCache()]), 'view' => new View(), 'dependency' => [ 'class' => ExpressionDependency::class, @@ -422,7 +423,7 @@ public function testDependency() Yii::$app->response->send(); ob_end_clean(); - $this->assertNotEmpty($this->getInaccessibleProperty($filter->cache, '_cache')); + $this->assertNotEmpty($this->getInaccessibleProperty($filter->cache->handler, '_cache')); // Verifies the cached response $this->destroyApplication(); diff --git a/tests/framework/rbac/MySQLManagerCacheTest.php b/tests/framework/rbac/MySQLManagerCacheTest.php index bb3ce87331e..8ca698cdc33 100644 --- a/tests/framework/rbac/MySQLManagerCacheTest.php +++ b/tests/framework/rbac/MySQLManagerCacheTest.php @@ -7,6 +7,7 @@ namespace yiiunit\framework\rbac; +use yii\caching\Cache; use yii\caching\FileCache; use yii\rbac\DbManager; @@ -25,7 +26,7 @@ protected function createManager() { return new DbManager([ 'db' => $this->getConnection(), - 'cache' => new FileCache(['cachePath' => '@yiiunit/runtime/cache']), + 'cache' => new Cache(['handler' => new FileCache(['cachePath' => '@yiiunit/runtime/cache'])]), 'defaultRoles' => ['myDefaultRole'], ]); } diff --git a/tests/framework/rbac/PgSQLManagerCacheTest.php b/tests/framework/rbac/PgSQLManagerCacheTest.php index 7451ba4fd10..c6bc1181452 100644 --- a/tests/framework/rbac/PgSQLManagerCacheTest.php +++ b/tests/framework/rbac/PgSQLManagerCacheTest.php @@ -7,6 +7,7 @@ namespace yiiunit\framework\rbac; +use yii\caching\Cache; use yii\caching\FileCache; use yii\rbac\DbManager; @@ -27,7 +28,7 @@ protected function createManager() { return new DbManager([ 'db' => $this->getConnection(), - 'cache' => new FileCache(['cachePath' => '@yiiunit/runtime/cache']), + 'cache' => new Cache(['handler' => new FileCache(['cachePath' => '@yiiunit/runtime/cache'])]), 'defaultRoles' => ['myDefaultRole'], ]); } diff --git a/tests/framework/web/CacheSessionTest.php b/tests/framework/web/CacheSessionTest.php index c73a960e02a..cae926ebc3d 100644 --- a/tests/framework/web/CacheSessionTest.php +++ b/tests/framework/web/CacheSessionTest.php @@ -8,7 +8,8 @@ namespace yiiunit\framework\web; use Yii; -use yii\caching\FileCache; +use yii\caching\ArrayCache; +use yii\caching\Cache; use yii\web\CacheSession; /** @@ -20,7 +21,7 @@ protected function setUp() { parent::setUp(); $this->mockApplication(); - Yii::$app->set('cache', new FileCache()); + Yii::$app->set('cache', new Cache(['handler' => new ArrayCache()])); } public function testCacheSession() diff --git a/tests/framework/widgets/FragmentCacheTest.php b/tests/framework/widgets/FragmentCacheTest.php index 24e0ed5a50e..5a23d4084bc 100644 --- a/tests/framework/widgets/FragmentCacheTest.php +++ b/tests/framework/widgets/FragmentCacheTest.php @@ -10,6 +10,7 @@ use Yii; use yii\base\View; use yii\caching\ArrayCache; +use yii\caching\Cache; /** * @group widgets @@ -22,7 +23,8 @@ protected function setUp() parent::setUp(); $this->mockWebApplication(); Yii::$app->set('cache', [ - 'class' => ArrayCache::class, + 'class' => Cache::class, + 'handler' => ArrayCache::class, ]); }